mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:23:52 +00:00
Merge branch 'openmw-27'
Conflicts: apps/launcher/graphicspage.hpp components/CMakeLists.txt
This commit is contained in:
commit
418ccf705d
240 changed files with 5262 additions and 3059 deletions
|
@ -319,6 +319,9 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.cfg
|
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.cfg
|
||||||
"${OpenMW_BINARY_DIR}/opencs.cfg")
|
"${OpenMW_BINARY_DIR}/opencs.cfg")
|
||||||
|
|
||||||
|
configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
|
||||||
|
"${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY)
|
||||||
|
|
||||||
if (NOT WIN32 AND NOT APPLE)
|
if (NOT WIN32 AND NOT APPLE)
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
||||||
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
||||||
|
@ -457,10 +460,20 @@ if(WIN32)
|
||||||
"${OpenMW_SOURCE_DIR}/Daedric Font License.txt"
|
"${OpenMW_SOURCE_DIR}/Daedric Font License.txt"
|
||||||
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
||||||
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
|
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
|
||||||
"${OpenMW_BINARY_DIR}/Release/mwiniimport.exe"
|
|
||||||
"${OpenMW_BINARY_DIR}/Release/omwlauncher.exe"
|
|
||||||
"${OpenMW_BINARY_DIR}/Release/openmw.exe"
|
"${OpenMW_BINARY_DIR}/Release/openmw.exe"
|
||||||
DESTINATION ".")
|
DESTINATION ".")
|
||||||
|
|
||||||
|
IF(BUILD_LAUNCHER)
|
||||||
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/omwlauncher.exe" DESTINATION ".")
|
||||||
|
ENDIF(BUILD_LAUNCHER)
|
||||||
|
IF(BUILD_MWINIIMPORTER)
|
||||||
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/mwiniimport.exe" DESTINATION ".")
|
||||||
|
ENDIF(BUILD_MWINIIMPORTER)
|
||||||
|
IF(BUILD_OPENCS)
|
||||||
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/opencs.exe" DESTINATION ".")
|
||||||
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.cfg" DESTINATION ".")
|
||||||
|
ENDIF(BUILD_OPENCS)
|
||||||
|
|
||||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
||||||
|
|
||||||
SET(CPACK_GENERATOR "NSIS")
|
SET(CPACK_GENERATOR "NSIS")
|
||||||
|
@ -470,7 +483,13 @@ if(WIN32)
|
||||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
|
SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR})
|
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR})
|
||||||
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||||
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;omwlauncher;OpenMW Launcher")
|
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW")
|
||||||
|
IF(BUILD_LAUNCHER)
|
||||||
|
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};omwlauncher;OpenMW Launcher")
|
||||||
|
ENDIF(BUILD_LAUNCHER)
|
||||||
|
IF(BUILD_OPENCS)
|
||||||
|
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};opencs;OpenMW Construction Set")
|
||||||
|
ENDIF(BUILD_OPENCS)
|
||||||
SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\readme.txt'")
|
SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\readme.txt'")
|
||||||
SET(CPACK_NSIS_DELETE_ICONS_EXTRA "
|
SET(CPACK_NSIS_DELETE_ICONS_EXTRA "
|
||||||
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
|
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
|
||||||
|
|
|
@ -305,14 +305,14 @@ 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.getGameFiles();
|
||||||
|
|
||||||
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;
|
||||||
std::vector<ESM::Header::MasterData> m = esm.getMasters();
|
std::vector<ESM::Header::MasterData> m = esm.getGameFiles();
|
||||||
if (!m.empty())
|
if (!m.empty())
|
||||||
{
|
{
|
||||||
std::cout << "Masters:" << std::endl;
|
std::cout << "Masters:" << std::endl;
|
||||||
|
|
|
@ -11,7 +11,9 @@ set(LAUNCHER
|
||||||
settings/launchersettings.cpp
|
settings/launchersettings.cpp
|
||||||
|
|
||||||
utils/checkablemessagebox.cpp
|
utils/checkablemessagebox.cpp
|
||||||
|
utils/profilescombobox.cpp
|
||||||
utils/textinputdialog.cpp
|
utils/textinputdialog.cpp
|
||||||
|
utils/lineedit.cpp
|
||||||
|
|
||||||
${CMAKE_SOURCE_DIR}/files/launcher/launcher.rc
|
${CMAKE_SOURCE_DIR}/files/launcher/launcher.rc
|
||||||
)
|
)
|
||||||
|
@ -32,8 +34,9 @@ set(LAUNCHER_HEADER
|
||||||
settings/settingsbase.hpp
|
settings/settingsbase.hpp
|
||||||
|
|
||||||
utils/checkablemessagebox.hpp
|
utils/checkablemessagebox.hpp
|
||||||
|
utils/profilescombobox.hpp
|
||||||
utils/textinputdialog.hpp
|
utils/textinputdialog.hpp
|
||||||
|
utils/lineedit.hpp
|
||||||
)
|
)
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
LIST(APPEND LAUNCHER_HEADER unshieldthread.hpp)
|
LIST(APPEND LAUNCHER_HEADER unshieldthread.hpp)
|
||||||
|
@ -48,8 +51,11 @@ set(LAUNCHER_HEADER_MOC
|
||||||
playpage.hpp
|
playpage.hpp
|
||||||
textslotmsgbox.hpp
|
textslotmsgbox.hpp
|
||||||
|
|
||||||
utils/checkablemessagebox.hpp
|
|
||||||
utils/textinputdialog.hpp
|
utils/textinputdialog.hpp
|
||||||
|
utils/checkablemessagebox.hpp
|
||||||
|
utils/profilescombobox.hpp
|
||||||
|
utils/lineedit.hpp
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
|
@ -62,6 +68,7 @@ set(LAUNCHER_UI
|
||||||
${CMAKE_SOURCE_DIR}/files/ui/graphicspage.ui
|
${CMAKE_SOURCE_DIR}/files/ui/graphicspage.ui
|
||||||
${CMAKE_SOURCE_DIR}/files/ui/mainwindow.ui
|
${CMAKE_SOURCE_DIR}/files/ui/mainwindow.ui
|
||||||
${CMAKE_SOURCE_DIR}/files/ui/playpage.ui
|
${CMAKE_SOURCE_DIR}/files/ui/playpage.ui
|
||||||
|
${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})
|
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})
|
||||||
|
|
|
@ -4,548 +4,307 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
#include <components/fileorderlist/model/datafilesmodel.hpp>
|
#include <components/contentselector/model/esmfile.hpp>
|
||||||
#include <components/fileorderlist/model/pluginsproxymodel.hpp>
|
|
||||||
#include <components/fileorderlist/model/esm/esmfile.hpp>
|
|
||||||
|
|
||||||
#include <components/fileorderlist/utils/lineedit.hpp>
|
#include <components/contentselector/model/naturalsort.hpp>
|
||||||
#include <components/fileorderlist/utils/naturalsort.hpp>
|
|
||||||
#include <components/fileorderlist/utils/profilescombobox.hpp>
|
#include "utils/textinputdialog.hpp"
|
||||||
|
#include "utils/profilescombobox.hpp"
|
||||||
|
|
||||||
#include "settings/gamesettings.hpp"
|
#include "settings/gamesettings.hpp"
|
||||||
#include "settings/launchersettings.hpp"
|
#include "settings/launchersettings.hpp"
|
||||||
|
|
||||||
#include "utils/textinputdialog.hpp"
|
#include "components/contentselector/view/contentselector.hpp"
|
||||||
|
|
||||||
DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent)
|
Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent)
|
||||||
: mCfgMgr(cfg)
|
: mCfgMgr(cfg)
|
||||||
, mGameSettings(gameSettings)
|
, mGameSettings(gameSettings)
|
||||||
, mLauncherSettings(launcherSettings)
|
, mLauncherSettings(launcherSettings)
|
||||||
, QWidget(parent)
|
, QWidget(parent)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
ui.setupUi (this);
|
||||||
|
setObjectName ("DataFilesPage");
|
||||||
|
mSelector = new ContentSelectorView::ContentSelector (ui.contentSelectorWidget);
|
||||||
|
|
||||||
// Models
|
buildView();
|
||||||
mDataFilesModel = new DataFilesModel(this);
|
|
||||||
|
|
||||||
mMastersProxyModel = new QSortFilterProxyModel();
|
|
||||||
mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm"));
|
|
||||||
mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
||||||
mMastersProxyModel->setSourceModel(mDataFilesModel);
|
|
||||||
|
|
||||||
mPluginsProxyModel = new PluginsProxyModel();
|
|
||||||
mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp"));
|
|
||||||
mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
||||||
mPluginsProxyModel->setSourceModel(mDataFilesModel);
|
|
||||||
|
|
||||||
mFilterProxyModel = new QSortFilterProxyModel();
|
|
||||||
mFilterProxyModel->setDynamicSortFilter(true);
|
|
||||||
mFilterProxyModel->setSourceModel(mPluginsProxyModel);
|
|
||||||
|
|
||||||
QCheckBox checkBox;
|
|
||||||
unsigned int height = checkBox.sizeHint().height() + 4;
|
|
||||||
|
|
||||||
mastersTable->setModel(mMastersProxyModel);
|
|
||||||
mastersTable->setObjectName("MastersTable");
|
|
||||||
mastersTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
mastersTable->setSortingEnabled(false);
|
|
||||||
mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
||||||
mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
||||||
mastersTable->setAlternatingRowColors(true);
|
|
||||||
mastersTable->horizontalHeader()->setStretchLastSection(true);
|
|
||||||
mastersTable->horizontalHeader()->hide();
|
|
||||||
|
|
||||||
// Set the row height to the size of the checkboxes
|
|
||||||
mastersTable->verticalHeader()->setDefaultSectionSize(height);
|
|
||||||
mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
|
||||||
mastersTable->verticalHeader()->hide();
|
|
||||||
|
|
||||||
pluginsTable->setModel(mFilterProxyModel);
|
|
||||||
pluginsTable->setObjectName("PluginsTable");
|
|
||||||
pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
pluginsTable->setSortingEnabled(false);
|
|
||||||
pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
||||||
pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
||||||
pluginsTable->setAlternatingRowColors(true);
|
|
||||||
pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
|
|
||||||
pluginsTable->horizontalHeader()->setStretchLastSection(true);
|
|
||||||
pluginsTable->horizontalHeader()->hide();
|
|
||||||
|
|
||||||
pluginsTable->verticalHeader()->setDefaultSectionSize(height);
|
|
||||||
pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
|
||||||
|
|
||||||
// Adjust the tableview widths inside the splitter
|
|
||||||
QList<int> sizeList;
|
|
||||||
sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt();
|
|
||||||
sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt();
|
|
||||||
|
|
||||||
splitter->setSizes(sizeList);
|
|
||||||
|
|
||||||
// Create a dialog for the new profile name input
|
|
||||||
mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this);
|
|
||||||
|
|
||||||
connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
|
|
||||||
|
|
||||||
connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString)));
|
|
||||||
|
|
||||||
connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
|
||||||
connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
|
||||||
|
|
||||||
connect(pluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
|
||||||
connect(mastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
|
||||||
|
|
||||||
connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews()));
|
|
||||||
|
|
||||||
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
|
|
||||||
|
|
||||||
connect(splitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter()));
|
|
||||||
|
|
||||||
createActions();
|
|
||||||
setupDataFiles();
|
setupDataFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::createActions()
|
void Launcher::DataFilesPage::loadSettings()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Add the actions to the toolbuttons
|
|
||||||
newProfileButton->setDefaultAction(newProfileAction);
|
|
||||||
deleteProfileButton->setDefaultAction(deleteProfileAction);
|
|
||||||
|
|
||||||
// Context menu actions
|
|
||||||
mContextMenu = new QMenu(this);
|
|
||||||
mContextMenu->addAction(checkAction);
|
|
||||||
mContextMenu->addAction(uncheckAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::setupDataFiles()
|
|
||||||
{
|
|
||||||
// Set the encoding to the one found in openmw.cfg or the default
|
|
||||||
mDataFilesModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252")));
|
|
||||||
|
|
||||||
QStringList paths = mGameSettings.getDataDirs();
|
QStringList paths = mGameSettings.getDataDirs();
|
||||||
|
paths.insert (0, mDataLocal);
|
||||||
|
PathIterator pathIterator (paths);
|
||||||
|
|
||||||
foreach (const QString &path, paths) {
|
QString profileName = ui.profilesComboBox->currentText();
|
||||||
mDataFilesModel->addFiles(path);
|
|
||||||
|
QStringList files = mLauncherSettings.values(QString("Profiles/") + profileName, Qt::MatchExactly);
|
||||||
|
|
||||||
|
QStringList filepaths;
|
||||||
|
|
||||||
|
foreach (const QString &file, files)
|
||||||
|
{
|
||||||
|
QString filepath = pathIterator.findFirstPath (file);
|
||||||
|
|
||||||
|
if (!filepath.isEmpty())
|
||||||
|
filepaths << filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString dataLocal = mGameSettings.getDataLocal();
|
mSelector->setProfileContent (filepaths);
|
||||||
if (!dataLocal.isEmpty())
|
|
||||||
mDataFilesModel->addFiles(dataLocal);
|
|
||||||
|
|
||||||
// Sort by date accessed for now
|
|
||||||
mDataFilesModel->sort(3);
|
|
||||||
|
|
||||||
QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/"));
|
|
||||||
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
|
|
||||||
|
|
||||||
if (!profiles.isEmpty())
|
|
||||||
profilesComboBox->addItems(profiles);
|
|
||||||
|
|
||||||
// Add the current profile if empty
|
|
||||||
if (profilesComboBox->findText(profile) == -1 && !profile.isEmpty())
|
|
||||||
profilesComboBox->addItem(profile);
|
|
||||||
|
|
||||||
if (profilesComboBox->findText(QString("Default")) == -1)
|
|
||||||
profilesComboBox->addItem(QString("Default"));
|
|
||||||
|
|
||||||
if (profile.isEmpty() || profile == QLatin1String("Default")) {
|
|
||||||
deleteProfileAction->setEnabled(false);
|
|
||||||
profilesComboBox->setEditEnabled(false);
|
|
||||||
profilesComboBox->setCurrentIndex(profilesComboBox->findText(QString("Default")));
|
|
||||||
} else {
|
|
||||||
profilesComboBox->setEditEnabled(true);
|
|
||||||
profilesComboBox->setCurrentIndex(profilesComboBox->findText(profile));
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do this here to prevent deletion of profiles when initializing the combobox
|
|
||||||
connect(profilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString)));
|
|
||||||
connect(profilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString)));
|
|
||||||
|
|
||||||
loadSettings();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::loadSettings()
|
void Launcher::DataFilesPage::saveSettings(const QString &profile)
|
||||||
{
|
{
|
||||||
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
|
QString profileName = profile;
|
||||||
|
|
||||||
if (profile.isEmpty())
|
if (profileName.isEmpty())
|
||||||
return;
|
profileName = ui.profilesComboBox->currentText();
|
||||||
|
|
||||||
mDataFilesModel->uncheckAll();
|
//retrieve the files selected for the profile
|
||||||
|
ContentSelectorModel::ContentFileList items = mSelector->selectedFiles();
|
||||||
|
|
||||||
QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly);
|
removeProfile (profileName);
|
||||||
QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly);
|
|
||||||
|
|
||||||
foreach (const QString &master, masters) {
|
mGameSettings.remove(QString("content"));
|
||||||
QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(master));
|
|
||||||
if (index.isValid())
|
|
||||||
mDataFilesModel->setCheckState(index, Qt::Checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const QString &plugin, plugins) {
|
//set the value of the current profile (not necessarily the profile being saved!)
|
||||||
QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(plugin));
|
mLauncherSettings.setValue(QString("Profiles/currentprofile"), ui.profilesComboBox->currentText());
|
||||||
if (index.isValid())
|
|
||||||
mDataFilesModel->setCheckState(index, Qt::Checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::saveSettings()
|
foreach(const ContentSelectorModel::EsmFile *item, items) {
|
||||||
{
|
|
||||||
if (mDataFilesModel->rowCount() < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
|
if (item->gameFiles().size() == 0) {
|
||||||
|
mLauncherSettings.setMultiValue(QString("Profiles/") + profileName, item->fileName());
|
||||||
if (profile.isEmpty()) {
|
mGameSettings.setMultiValue(QString("content"), item->fileName());
|
||||||
profile = profilesComboBox->currentText();
|
} else {
|
||||||
mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile);
|
mLauncherSettings.setMultiValue(QString("Profiles/") + profileName, item->fileName());
|
||||||
}
|
mGameSettings.setMultiValue(QString("content"), item->fileName());
|
||||||
|
|
||||||
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master"));
|
|
||||||
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin"));
|
|
||||||
|
|
||||||
mGameSettings.remove(QString("master"));
|
|
||||||
mGameSettings.remove(QString("plugin"));
|
|
||||||
|
|
||||||
QStringList items = mDataFilesModel->checkedItems();
|
|
||||||
|
|
||||||
foreach(const QString &item, items) {
|
|
||||||
|
|
||||||
if (item.endsWith(QString(".esm"), Qt::CaseInsensitive)) {
|
|
||||||
mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item);
|
|
||||||
mGameSettings.setMultiValue(QString("master"), item);
|
|
||||||
|
|
||||||
} else if (item.endsWith(QString(".esp"), Qt::CaseInsensitive)) {
|
|
||||||
mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item);
|
|
||||||
mGameSettings.setMultiValue(QString("plugin"), item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::updateOkButton(const QString &text)
|
void Launcher::DataFilesPage::buildView()
|
||||||
{
|
{
|
||||||
// We do this here because we need the profiles combobox text
|
ui.verticalLayout->insertWidget (0, mSelector->uiWidget());
|
||||||
if (text.isEmpty()) {
|
|
||||||
mNewProfileDialog->setOkButtonEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
(profilesComboBox->findText(text) == -1)
|
//tool buttons
|
||||||
? mNewProfileDialog->setOkButtonEnabled(true)
|
ui.newProfileButton->setToolTip ("Create a new profile");
|
||||||
: mNewProfileDialog->setOkButtonEnabled(false);
|
ui.deleteProfileButton->setToolTip ("Delete an existing profile");
|
||||||
|
|
||||||
|
//combo box
|
||||||
|
ui.profilesComboBox->addItem ("Default");
|
||||||
|
ui.profilesComboBox->setPlaceholderText (QString("Select a profile..."));
|
||||||
|
|
||||||
|
// Add the actions to the toolbuttons
|
||||||
|
ui.newProfileButton->setDefaultAction (ui.newProfileAction);
|
||||||
|
ui.deleteProfileButton->setDefaultAction (ui.deleteProfileAction);
|
||||||
|
|
||||||
|
//establish connections
|
||||||
|
connect (ui.profilesComboBox, SIGNAL (currentIndexChanged(int)),
|
||||||
|
this, SLOT (slotProfileChanged(int)));
|
||||||
|
|
||||||
|
connect (ui.profilesComboBox, SIGNAL (profileRenamed(QString, QString)),
|
||||||
|
this, SLOT (slotProfileRenamed(QString, QString)));
|
||||||
|
|
||||||
|
connect (ui.profilesComboBox, SIGNAL (signalProfileChanged(QString, QString)),
|
||||||
|
this, SLOT (slotProfileChangedByUser(QString, QString)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::updateSplitter()
|
void Launcher::DataFilesPage::removeProfile(const QString &profile)
|
||||||
{
|
{
|
||||||
// Sigh, update the saved splitter size in settings only when moved
|
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/game"));
|
||||||
// Since getting mSplitter->sizes() if page is hidden returns invalid values
|
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/addon"));
|
||||||
QList<int> sizes = splitter->sizes();
|
|
||||||
|
|
||||||
mLauncherSettings.setValue(QString("General/MastersTable/width"), QString::number(sizes.at(0)));
|
|
||||||
mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::updateViews()
|
QAbstractItemModel *Launcher::DataFilesPage::profilesModel() const
|
||||||
{
|
{
|
||||||
// Ensure the columns are hidden because sort() re-enables them
|
return ui.profilesComboBox->model();
|
||||||
mastersTable->setColumnHidden(1, true);
|
|
||||||
mastersTable->setColumnHidden(2, true);
|
|
||||||
mastersTable->setColumnHidden(3, true);
|
|
||||||
mastersTable->setColumnHidden(4, true);
|
|
||||||
mastersTable->setColumnHidden(5, true);
|
|
||||||
mastersTable->setColumnHidden(6, true);
|
|
||||||
mastersTable->setColumnHidden(7, true);
|
|
||||||
mastersTable->setColumnHidden(8, true);
|
|
||||||
|
|
||||||
pluginsTable->setColumnHidden(1, true);
|
|
||||||
pluginsTable->setColumnHidden(2, true);
|
|
||||||
pluginsTable->setColumnHidden(3, true);
|
|
||||||
pluginsTable->setColumnHidden(4, true);
|
|
||||||
pluginsTable->setColumnHidden(5, true);
|
|
||||||
pluginsTable->setColumnHidden(6, true);
|
|
||||||
pluginsTable->setColumnHidden(7, true);
|
|
||||||
pluginsTable->setColumnHidden(8, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::setProfilesComboBoxIndex(int index)
|
int Launcher::DataFilesPage::profilesIndex() const
|
||||||
{
|
{
|
||||||
profilesComboBox->setCurrentIndex(index);
|
return ui.profilesComboBox->currentIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::slotCurrentIndexChanged(int index)
|
void Launcher::DataFilesPage::setProfile(int index, bool savePrevious)
|
||||||
{
|
{
|
||||||
emit profileChanged(index);
|
if (index >= -1 && index < ui.profilesComboBox->count())
|
||||||
}
|
{
|
||||||
|
QString previous = ui.profilesComboBox->itemText(ui.profilesComboBox->currentIndex());
|
||||||
|
QString current = ui.profilesComboBox->itemText(index);
|
||||||
|
|
||||||
QAbstractItemModel* DataFilesPage::profilesComboBoxModel()
|
setProfile (previous, current, savePrevious);
|
||||||
{
|
|
||||||
return profilesComboBox->model();
|
|
||||||
}
|
|
||||||
|
|
||||||
int DataFilesPage::profilesComboBoxIndex()
|
|
||||||
{
|
|
||||||
return profilesComboBox->currentIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::on_newProfileAction_triggered()
|
|
||||||
{
|
|
||||||
if (mNewProfileDialog->exec() == QDialog::Accepted) {
|
|
||||||
QString profile = mNewProfileDialog->lineEdit()->text();
|
|
||||||
profilesComboBox->addItem(profile);
|
|
||||||
profilesComboBox->setCurrentIndex(profilesComboBox->findText(profile));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFilesPage::on_deleteProfileAction_triggered()
|
void Launcher::DataFilesPage::setProfile (const QString &previous, const QString ¤t, bool savePrevious)
|
||||||
{
|
{
|
||||||
QString profile = profilesComboBox->currentText();
|
//abort if no change (poss. duplicate signal)
|
||||||
|
if (previous == current)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!previous.isEmpty() && savePrevious)
|
||||||
|
saveSettings (previous);
|
||||||
|
|
||||||
|
ui.profilesComboBox->setCurrentProfile (ui.profilesComboBox->findText (current));
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
|
|
||||||
|
checkForDefaultProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::slotProfileDeleted (const QString &item)
|
||||||
|
{
|
||||||
|
removeProfile (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::slotProfileChangedByUser(const QString &previous, const QString ¤t)
|
||||||
|
{
|
||||||
|
setProfile(previous, current, true);
|
||||||
|
emit signalProfileChanged (ui.profilesComboBox->findText(current));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::slotProfileRenamed(const QString &previous, const QString ¤t)
|
||||||
|
{
|
||||||
|
if (previous.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Save the new profile name
|
||||||
|
saveSettings();
|
||||||
|
|
||||||
|
// Remove the old one
|
||||||
|
removeProfile (previous);
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::slotProfileChanged(int index)
|
||||||
|
{
|
||||||
|
setProfile (index, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::setupDataFiles()
|
||||||
|
{
|
||||||
|
QStringList paths = mGameSettings.getDataDirs();
|
||||||
|
|
||||||
|
foreach (const QString &path, paths)
|
||||||
|
mSelector->addFiles(path);
|
||||||
|
|
||||||
|
mDataLocal = mGameSettings.getDataLocal();
|
||||||
|
|
||||||
|
if (!mDataLocal.isEmpty())
|
||||||
|
mSelector->addFiles(mDataLocal);
|
||||||
|
|
||||||
|
QStringList profiles;
|
||||||
|
QString currentProfile = mLauncherSettings.getSettings().value("Profiles/currentprofile");
|
||||||
|
|
||||||
|
foreach (QString key, mLauncherSettings.getSettings().keys())
|
||||||
|
{
|
||||||
|
if (key.contains("Profiles/"))
|
||||||
|
{
|
||||||
|
QString profile = key.mid (9);
|
||||||
|
if (profile != "currentprofile")
|
||||||
|
{
|
||||||
|
if (!profiles.contains(profile))
|
||||||
|
profiles << profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QString &item, profiles)
|
||||||
|
addProfile (item, false);
|
||||||
|
|
||||||
|
setProfile (ui.profilesComboBox->findText(currentProfile), false);
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::on_newProfileAction_triggered()
|
||||||
|
{
|
||||||
|
TextInputDialog newDialog (tr("New Profile"), tr("Profile name:"), this);
|
||||||
|
|
||||||
|
if (newDialog.exec() != QDialog::Accepted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString profile = newDialog.getText();
|
||||||
|
|
||||||
|
if (profile.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
saveSettings();
|
||||||
|
|
||||||
|
mSelector->clearCheckStates();
|
||||||
|
|
||||||
|
addProfile(profile, true);
|
||||||
|
|
||||||
|
mSelector->setGameFile();
|
||||||
|
|
||||||
|
saveSettings();
|
||||||
|
|
||||||
|
emit signalProfileChanged (ui.profilesComboBox->findText(profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::addProfile (const QString &profile, bool setAsCurrent)
|
||||||
|
{
|
||||||
|
if (profile.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ui.profilesComboBox->findText (profile) != -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ui.profilesComboBox->addItem (profile);
|
||||||
|
|
||||||
|
if (setAsCurrent)
|
||||||
|
setProfile (ui.profilesComboBox->findText (profile), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::on_deleteProfileAction_triggered()
|
||||||
|
{
|
||||||
|
QString profile = ui.profilesComboBox->currentText();
|
||||||
|
|
||||||
if (profile.isEmpty())
|
if (profile.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!showDeleteMessageBox (profile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remove the profile from the combobox
|
||||||
|
ui.profilesComboBox->removeItem (ui.profilesComboBox->findText (profile));
|
||||||
|
|
||||||
|
removeProfile(profile);
|
||||||
|
|
||||||
|
saveSettings();
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
|
|
||||||
|
checkForDefaultProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::checkForDefaultProfile()
|
||||||
|
{
|
||||||
|
//don't allow deleting "Default" profile
|
||||||
|
bool success = (ui.profilesComboBox->currentText() != "Default");
|
||||||
|
|
||||||
|
ui.deleteProfileAction->setEnabled (success);
|
||||||
|
ui.profilesComboBox->setEditEnabled (success);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text)
|
||||||
|
{
|
||||||
QMessageBox msgBox(this);
|
QMessageBox msgBox(this);
|
||||||
msgBox.setWindowTitle(tr("Delete Profile"));
|
msgBox.setWindowTitle(tr("Delete Profile"));
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::Cancel);
|
msgBox.setStandardButtons(QMessageBox::Cancel);
|
||||||
msgBox.setText(tr("Are you sure you want to delete <b>%0</b>?").arg(profile));
|
msgBox.setText(tr("Are you sure you want to delete <b>%0</b>?").arg(text));
|
||||||
|
|
||||||
QAbstractButton *deleteButton =
|
QAbstractButton *deleteButton =
|
||||||
msgBox.addButton(tr("Delete"), QMessageBox::ActionRole);
|
msgBox.addButton(tr("Delete"), QMessageBox::ActionRole);
|
||||||
|
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
|
|
||||||
if (msgBox.clickedButton() == deleteButton) {
|
return (msgBox.clickedButton() == deleteButton);
|
||||||
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master"));
|
|
||||||
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin"));
|
|
||||||
|
|
||||||
// Remove the profile from the combobox
|
|
||||||
profilesComboBox->removeItem(profilesComboBox->findText(profile));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::on_checkAction_triggered()
|
|
||||||
{
|
|
||||||
if (pluginsTable->hasFocus())
|
|
||||||
setPluginsCheckstates(Qt::Checked);
|
|
||||||
|
|
||||||
if (mastersTable->hasFocus())
|
|
||||||
setMastersCheckstates(Qt::Checked);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::on_uncheckAction_triggered()
|
|
||||||
{
|
|
||||||
if (pluginsTable->hasFocus())
|
|
||||||
setPluginsCheckstates(Qt::Unchecked);
|
|
||||||
|
|
||||||
if (mastersTable->hasFocus())
|
|
||||||
setMastersCheckstates(Qt::Unchecked);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::setMastersCheckstates(Qt::CheckState state)
|
|
||||||
{
|
|
||||||
if (!mastersTable->selectionModel()->hasSelection()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes();
|
|
||||||
|
|
||||||
foreach (const QModelIndex &index, indexes)
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
|
|
||||||
|
|
||||||
if (!sourceIndex.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
mDataFilesModel->setCheckState(sourceIndex, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::setPluginsCheckstates(Qt::CheckState state)
|
|
||||||
{
|
|
||||||
if (!pluginsTable->selectionModel()->hasSelection()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes();
|
|
||||||
|
|
||||||
foreach (const QModelIndex &index, indexes)
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
|
|
||||||
mFilterProxyModel->mapToSource(index));
|
|
||||||
|
|
||||||
if (!sourceIndex.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
mDataFilesModel->setCheckState(sourceIndex, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::setCheckState(QModelIndex index)
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QObject *object = QObject::sender();
|
|
||||||
|
|
||||||
// Not a signal-slot call
|
|
||||||
if (!object)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
if (object->objectName() == QLatin1String("PluginsTable")) {
|
|
||||||
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
|
|
||||||
mFilterProxyModel->mapToSource(index));
|
|
||||||
|
|
||||||
if (sourceIndex.isValid()) {
|
|
||||||
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
|
||||||
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
|
|
||||||
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (object->objectName() == QLatin1String("MastersTable")) {
|
|
||||||
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
|
|
||||||
|
|
||||||
if (sourceIndex.isValid()) {
|
|
||||||
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
|
||||||
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
|
|
||||||
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::filterChanged(const QString filter)
|
|
||||||
{
|
|
||||||
QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString);
|
|
||||||
mFilterProxyModel->setFilterRegExp(regExp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::profileChanged(const QString &previous, const QString ¤t)
|
|
||||||
{
|
|
||||||
// Prevent the deletion of the default profile
|
|
||||||
if (current == QLatin1String("Default")) {
|
|
||||||
deleteProfileAction->setEnabled(false);
|
|
||||||
profilesComboBox->setEditEnabled(false);
|
|
||||||
} else {
|
|
||||||
deleteProfileAction->setEnabled(true);
|
|
||||||
profilesComboBox->setEditEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (profilesComboBox->findText(previous) == -1)
|
|
||||||
return; // Profile was deleted
|
|
||||||
|
|
||||||
// Store the previous profile
|
|
||||||
mLauncherSettings.setValue(QString("Profiles/currentprofile"), previous);
|
|
||||||
saveSettings();
|
|
||||||
mLauncherSettings.setValue(QString("Profiles/currentprofile"), current);
|
|
||||||
|
|
||||||
loadSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::profileRenamed(const QString &previous, const QString ¤t)
|
|
||||||
{
|
|
||||||
if (previous.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Save the new profile name
|
|
||||||
mLauncherSettings.setValue(QString("Profiles/currentprofile"), current);
|
|
||||||
saveSettings();
|
|
||||||
|
|
||||||
// Remove the old one
|
|
||||||
mLauncherSettings.remove(QString("Profiles/") + previous + QString("/master"));
|
|
||||||
mLauncherSettings.remove(QString("Profiles/") + previous + QString("/plugin"));
|
|
||||||
|
|
||||||
// Remove the profile from the combobox
|
|
||||||
profilesComboBox->removeItem(profilesComboBox->findText(previous));
|
|
||||||
|
|
||||||
loadSettings();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataFilesPage::showContextMenu(const QPoint &point)
|
|
||||||
{
|
|
||||||
QObject *object = QObject::sender();
|
|
||||||
|
|
||||||
// Not a signal-slot call
|
|
||||||
if (!object)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (object->objectName() == QLatin1String("PluginsTable")) {
|
|
||||||
if (!pluginsTable->selectionModel()->hasSelection())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QPoint globalPos = pluginsTable->mapToGlobal(point);
|
|
||||||
QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes();
|
|
||||||
|
|
||||||
// Show the check/uncheck actions depending on the state of the selected items
|
|
||||||
uncheckAction->setEnabled(false);
|
|
||||||
checkAction->setEnabled(false);
|
|
||||||
|
|
||||||
foreach (const QModelIndex &index, indexes)
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
|
|
||||||
mFilterProxyModel->mapToSource(index));
|
|
||||||
|
|
||||||
if (!sourceIndex.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
|
||||||
? uncheckAction->setEnabled(true)
|
|
||||||
: checkAction->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show menu
|
|
||||||
mContextMenu->exec(globalPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (object->objectName() == QLatin1String("MastersTable")) {
|
|
||||||
if (!mastersTable->selectionModel()->hasSelection())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QPoint globalPos = mastersTable->mapToGlobal(point);
|
|
||||||
QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes();
|
|
||||||
|
|
||||||
// Show the check/uncheck actions depending on the state of the selected items
|
|
||||||
uncheckAction->setEnabled(false);
|
|
||||||
checkAction->setEnabled(false);
|
|
||||||
|
|
||||||
foreach (const QModelIndex &index, indexes)
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
|
|
||||||
|
|
||||||
if (!sourceIndex.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
|
||||||
? uncheckAction->setEnabled(true)
|
|
||||||
: checkAction->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
mContextMenu->exec(globalPos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,88 +1,136 @@
|
||||||
#ifndef DATAFILESPAGE_H
|
#ifndef DATAFILESPAGE_H
|
||||||
#define DATAFILESPAGE_H
|
#define DATAFILESPAGE_H
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QModelIndex>
|
|
||||||
|
|
||||||
#include "ui_datafilespage.h"
|
#include "ui_datafilespage.h"
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
class QSortFilterProxyModel;
|
class QSortFilterProxyModel;
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
class QAction;
|
|
||||||
class QMenu;
|
class QMenu;
|
||||||
|
|
||||||
class DataFilesModel;
|
|
||||||
class TextInputDialog;
|
|
||||||
class GameSettings;
|
|
||||||
class LauncherSettings;
|
|
||||||
class PluginsProxyModel;
|
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files { struct ConfigurationManager; }
|
||||||
|
namespace ContentSelectorView { class ContentSelector; }
|
||||||
|
|
||||||
class DataFilesPage : public QWidget, private Ui::DataFilesPage
|
namespace Launcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class TextInputDialog;
|
||||||
|
class GameSettings;
|
||||||
|
class LauncherSettings;
|
||||||
|
class ProfilesComboBox;
|
||||||
|
|
||||||
public:
|
class DataFilesPage : public QWidget
|
||||||
DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0);
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
QAbstractItemModel* profilesComboBoxModel();
|
ContentSelectorView::ContentSelector *mSelector;
|
||||||
int profilesComboBoxIndex();
|
Ui::DataFilesPage ui;
|
||||||
|
|
||||||
void writeConfig(QString profile = QString());
|
public:
|
||||||
void saveSettings();
|
explicit DataFilesPage (Files::ConfigurationManager &cfg, GameSettings &gameSettings,
|
||||||
|
LauncherSettings &launcherSettings, QWidget *parent = 0);
|
||||||
|
|
||||||
signals:
|
QAbstractItemModel* profilesModel() const;
|
||||||
void profileChanged(int index);
|
|
||||||
|
|
||||||
public slots:
|
int profilesIndex() const;
|
||||||
void setCheckState(QModelIndex index);
|
|
||||||
void setProfilesComboBoxIndex(int index);
|
|
||||||
|
|
||||||
void filterChanged(const QString filter);
|
//void writeConfig(QString profile = QString());
|
||||||
void showContextMenu(const QPoint &point);
|
void saveSettings(const QString &profile = "");
|
||||||
void profileChanged(const QString &previous, const QString ¤t);
|
void loadSettings();
|
||||||
void profileRenamed(const QString &previous, const QString ¤t);
|
|
||||||
void updateOkButton(const QString &text);
|
|
||||||
void updateSplitter();
|
|
||||||
void updateViews();
|
|
||||||
|
|
||||||
// Action slots
|
signals:
|
||||||
void on_newProfileAction_triggered();
|
void signalProfileChanged (int index);
|
||||||
void on_deleteProfileAction_triggered();
|
|
||||||
void on_checkAction_triggered();
|
|
||||||
void on_uncheckAction_triggered();
|
|
||||||
|
|
||||||
private slots:
|
public slots:
|
||||||
void slotCurrentIndexChanged(int index);
|
void slotProfileChanged (int index);
|
||||||
|
|
||||||
private:
|
private slots:
|
||||||
DataFilesModel *mDataFilesModel;
|
|
||||||
|
|
||||||
PluginsProxyModel *mPluginsProxyModel;
|
void slotProfileChangedByUser(const QString &previous, const QString ¤t);
|
||||||
QSortFilterProxyModel *mMastersProxyModel;
|
void slotProfileRenamed(const QString &previous, const QString ¤t);
|
||||||
|
void slotProfileDeleted(const QString &item);
|
||||||
|
|
||||||
QSortFilterProxyModel *mFilterProxyModel;
|
void on_newProfileAction_triggered();
|
||||||
|
void on_deleteProfileAction_triggered();
|
||||||
|
|
||||||
QMenu *mContextMenu;
|
private:
|
||||||
|
|
||||||
Files::ConfigurationManager &mCfgMgr;
|
QMenu *mContextMenu;
|
||||||
|
|
||||||
GameSettings &mGameSettings;
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
LauncherSettings &mLauncherSettings;
|
|
||||||
|
|
||||||
TextInputDialog *mNewProfileDialog;
|
GameSettings &mGameSettings;
|
||||||
|
LauncherSettings &mLauncherSettings;
|
||||||
|
|
||||||
void setMastersCheckstates(Qt::CheckState state);
|
QString mDataLocal;
|
||||||
void setPluginsCheckstates(Qt::CheckState state);
|
|
||||||
|
|
||||||
void createActions();
|
void setPluginsCheckstates(Qt::CheckState state);
|
||||||
void setupDataFiles();
|
|
||||||
void setupConfig();
|
|
||||||
void readConfig();
|
|
||||||
|
|
||||||
void loadSettings();
|
void buildView();
|
||||||
|
void setupDataFiles();
|
||||||
|
void setupConfig();
|
||||||
|
void readConfig();
|
||||||
|
void setProfile (int index, bool savePrevious);
|
||||||
|
void setProfile (const QString &previous, const QString ¤t, bool savePrevious);
|
||||||
|
void removeProfile (const QString &profile);
|
||||||
|
bool showDeleteMessageBox (const QString &text);
|
||||||
|
void addProfile (const QString &profile, bool setAsCurrent);
|
||||||
|
void checkForDefaultProfile();
|
||||||
|
|
||||||
};
|
class PathIterator
|
||||||
|
{
|
||||||
|
QStringList::ConstIterator mCitEnd;
|
||||||
|
QStringList::ConstIterator mCitCurrent;
|
||||||
|
QStringList::ConstIterator mCitBegin;
|
||||||
|
QString mFile;
|
||||||
|
QString mFilePath;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PathIterator (const QStringList &list)
|
||||||
|
{
|
||||||
|
mCitBegin = list.constBegin();
|
||||||
|
mCitCurrent = mCitBegin;
|
||||||
|
mCitEnd = list.constEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString findFirstPath (const QString &file)
|
||||||
|
{
|
||||||
|
mCitCurrent = mCitBegin;
|
||||||
|
mFile = file;
|
||||||
|
return path();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString findNextPath () { return path(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QString path ()
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
QDir dir;
|
||||||
|
QFileInfo file;
|
||||||
|
|
||||||
|
while (!success)
|
||||||
|
{
|
||||||
|
if (mCitCurrent == mCitEnd)
|
||||||
|
break;
|
||||||
|
|
||||||
|
dir.setPath (*(mCitCurrent++));
|
||||||
|
file.setFile (dir.absoluteFilePath (mFile));
|
||||||
|
|
||||||
|
success = file.exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return file.absoluteFilePath();
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
#include <components/fileorderlist/utils/naturalsort.hpp>
|
#include <components/contentselector/model/naturalsort.hpp>
|
||||||
|
|
||||||
#include "settings/graphicssettings.hpp"
|
#include "settings/graphicssettings.hpp"
|
||||||
|
|
||||||
|
@ -30,11 +30,12 @@ QString getAspect(int x, int y)
|
||||||
return QString(QString::number(xaspect) + ":" + QString::number(yaspect));
|
return QString(QString::number(xaspect) + ":" + QString::number(yaspect));
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent)
|
Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent)
|
||||||
: mCfgMgr(cfg)
|
: mCfgMgr(cfg)
|
||||||
, mGraphicsSettings(graphicsSetting)
|
, mGraphicsSettings(graphicsSetting)
|
||||||
, QWidget(parent)
|
, QWidget(parent)
|
||||||
{
|
{
|
||||||
|
setObjectName ("GraphicsPage");
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
// Set the maximum res we can set in windowed mode
|
// Set the maximum res we can set in windowed mode
|
||||||
|
@ -49,7 +50,7 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &g
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsPage::setupOgre()
|
bool Launcher::GraphicsPage::setupOgre()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -115,7 +116,7 @@ bool GraphicsPage::setupOgre()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsPage::setupSDL()
|
bool Launcher::GraphicsPage::setupSDL()
|
||||||
{
|
{
|
||||||
int displays = SDL_GetNumVideoDisplays();
|
int displays = SDL_GetNumVideoDisplays();
|
||||||
|
|
||||||
|
@ -138,7 +139,7 @@ bool GraphicsPage::setupSDL()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsPage::loadSettings()
|
bool Launcher::GraphicsPage::loadSettings()
|
||||||
{
|
{
|
||||||
if (!setupSDL())
|
if (!setupSDL())
|
||||||
return false;
|
return false;
|
||||||
|
@ -177,7 +178,7 @@ bool GraphicsPage::loadSettings()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPage::saveSettings()
|
void Launcher::GraphicsPage::saveSettings()
|
||||||
{
|
{
|
||||||
vSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true"))
|
vSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true"))
|
||||||
: mGraphicsSettings.setValue(QString("Video/vsync"), QString("false"));
|
: mGraphicsSettings.setValue(QString("Video/vsync"), QString("false"));
|
||||||
|
@ -204,7 +205,7 @@ void GraphicsPage::saveSettings()
|
||||||
mGraphicsSettings.setValue(QString("Video/screen"), QString::number(screenComboBox->currentIndex()));
|
mGraphicsSettings.setValue(QString("Video/screen"), QString::number(screenComboBox->currentIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
|
QStringList Launcher::GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
|
||||||
|
@ -237,7 +238,7 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GraphicsPage::getAvailableResolutions(int screen)
|
QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
|
@ -284,7 +285,7 @@ QStringList GraphicsPage::getAvailableResolutions(int screen)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect GraphicsPage::getMaximumResolution()
|
QRect Launcher::GraphicsPage::getMaximumResolution()
|
||||||
{
|
{
|
||||||
QRect max;
|
QRect max;
|
||||||
int screens = QApplication::desktop()->screenCount();
|
int screens = QApplication::desktop()->screenCount();
|
||||||
|
@ -299,7 +300,7 @@ QRect GraphicsPage::getMaximumResolution()
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPage::rendererChanged(const QString &renderer)
|
void Launcher::GraphicsPage::rendererChanged(const QString &renderer)
|
||||||
{
|
{
|
||||||
mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString());
|
mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString());
|
||||||
|
|
||||||
|
@ -308,7 +309,7 @@ void GraphicsPage::rendererChanged(const QString &renderer)
|
||||||
antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
|
antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPage::screenChanged(int screen)
|
void Launcher::GraphicsPage::screenChanged(int screen)
|
||||||
{
|
{
|
||||||
if (screen >= 0) {
|
if (screen >= 0) {
|
||||||
resolutionComboBox->clear();
|
resolutionComboBox->clear();
|
||||||
|
@ -316,7 +317,7 @@ void GraphicsPage::screenChanged(int screen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPage::slotFullScreenChanged(int state)
|
void Launcher::GraphicsPage::slotFullScreenChanged(int state)
|
||||||
{
|
{
|
||||||
if (state == Qt::Checked) {
|
if (state == Qt::Checked) {
|
||||||
standardRadioButton->toggle();
|
standardRadioButton->toggle();
|
||||||
|
@ -330,7 +331,7 @@ void GraphicsPage::slotFullScreenChanged(int state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPage::slotStandardToggled(bool checked)
|
void Launcher::GraphicsPage::slotStandardToggled(bool checked)
|
||||||
{
|
{
|
||||||
if (checked) {
|
if (checked) {
|
||||||
resolutionComboBox->setEnabled(true);
|
resolutionComboBox->setEnabled(true);
|
||||||
|
|
|
@ -11,46 +11,47 @@
|
||||||
|
|
||||||
#include "ui_graphicspage.h"
|
#include "ui_graphicspage.h"
|
||||||
|
|
||||||
class GraphicsSettings;
|
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files { struct ConfigurationManager; }
|
||||||
|
|
||||||
class GraphicsPage : public QWidget, private Ui::GraphicsPage
|
namespace Launcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class GraphicsSettings;
|
||||||
|
|
||||||
public:
|
class GraphicsPage : public QWidget, private Ui::GraphicsPage
|
||||||
GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSettings, QWidget *parent = 0);
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
void saveSettings();
|
public:
|
||||||
bool loadSettings();
|
GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSettings, QWidget *parent = 0);
|
||||||
|
|
||||||
public slots:
|
void saveSettings();
|
||||||
void rendererChanged(const QString &renderer);
|
bool loadSettings();
|
||||||
void screenChanged(int screen);
|
|
||||||
|
|
||||||
private slots:
|
public slots:
|
||||||
void slotFullScreenChanged(int state);
|
void rendererChanged(const QString &renderer);
|
||||||
void slotStandardToggled(bool checked);
|
void screenChanged(int screen);
|
||||||
|
|
||||||
private:
|
private slots:
|
||||||
OgreInit::OgreInit mOgreInit;
|
void slotFullScreenChanged(int state);
|
||||||
|
void slotStandardToggled(bool checked);
|
||||||
|
|
||||||
Ogre::Root *mOgre;
|
private:
|
||||||
Ogre::RenderSystem *mSelectedRenderSystem;
|
OgreInit::OgreInit mOgreInit;
|
||||||
Ogre::RenderSystem *mOpenGLRenderSystem;
|
Ogre::Root *mOgre;
|
||||||
Ogre::RenderSystem *mDirect3DRenderSystem;
|
Ogre::RenderSystem *mSelectedRenderSystem;
|
||||||
|
Ogre::RenderSystem *mOpenGLRenderSystem;
|
||||||
|
Ogre::RenderSystem *mDirect3DRenderSystem;
|
||||||
|
|
||||||
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
|
GraphicsSettings &mGraphicsSettings;
|
||||||
|
|
||||||
Files::ConfigurationManager &mCfgMgr;
|
QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer);
|
||||||
GraphicsSettings &mGraphicsSettings;
|
QStringList getAvailableResolutions(int screen);
|
||||||
|
QRect getMaximumResolution();
|
||||||
QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer);
|
|
||||||
QStringList getAvailableResolutions(int screen);
|
|
||||||
QRect getMaximumResolution();
|
|
||||||
|
|
||||||
bool setupOgre();
|
|
||||||
bool setupSDL();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
bool setupOgre();
|
||||||
|
bool setupSDL();
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -47,7 +47,7 @@ int main(int argc, char *argv[])
|
||||||
// Support non-latin characters
|
// Support non-latin characters
|
||||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||||
|
|
||||||
MainDialog mainWin;
|
Launcher::MainDialog mainWin;
|
||||||
|
|
||||||
if (mainWin.setup()) {
|
if (mainWin.setup()) {
|
||||||
mainWin.show();
|
mainWin.show();
|
||||||
|
@ -59,4 +59,3 @@ int main(int argc, char *argv[])
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "maindialog.hpp"
|
#include "maindialog.hpp"
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
@ -23,8 +24,8 @@
|
||||||
#include "graphicspage.hpp"
|
#include "graphicspage.hpp"
|
||||||
#include "datafilespage.hpp"
|
#include "datafilespage.hpp"
|
||||||
|
|
||||||
MainDialog::MainDialog()
|
Launcher::MainDialog::MainDialog(QWidget *parent)
|
||||||
: mGameSettings(mCfgMgr)
|
: mGameSettings(mCfgMgr), QMainWindow (parent)
|
||||||
{
|
{
|
||||||
// Install the stylesheet font
|
// Install the stylesheet font
|
||||||
QFile file;
|
QFile file;
|
||||||
|
@ -69,7 +70,7 @@ MainDialog::MainDialog()
|
||||||
createIcons();
|
createIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::createIcons()
|
void Launcher::MainDialog::createIcons()
|
||||||
{
|
{
|
||||||
if (!QIcon::hasThemeIcon("document-new"))
|
if (!QIcon::hasThemeIcon("document-new"))
|
||||||
QIcon::setThemeName("tango");
|
QIcon::setThemeName("tango");
|
||||||
|
@ -101,15 +102,15 @@ void MainDialog::createIcons()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::createPages()
|
void Launcher::MainDialog::createPages()
|
||||||
{
|
{
|
||||||
mPlayPage = new PlayPage(this);
|
mPlayPage = new PlayPage(this);
|
||||||
mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this);
|
mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this);
|
||||||
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||||
|
|
||||||
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
||||||
mPlayPage->setProfilesComboBoxModel(mDataFilesPage->profilesComboBoxModel());
|
mPlayPage->setProfilesModel(mDataFilesPage->profilesModel());
|
||||||
mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->profilesComboBoxIndex());
|
mPlayPage->setProfilesIndex(mDataFilesPage->profilesIndex());
|
||||||
|
|
||||||
// Add the pages to the stacked widget
|
// Add the pages to the stacked widget
|
||||||
pagesWidget->addWidget(mPlayPage);
|
pagesWidget->addWidget(mPlayPage);
|
||||||
|
@ -121,12 +122,12 @@ void MainDialog::createPages()
|
||||||
|
|
||||||
connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play()));
|
connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play()));
|
||||||
|
|
||||||
connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage, SLOT(setProfilesComboBoxIndex(int)));
|
connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int)));
|
||||||
connect(mDataFilesPage, SIGNAL(profileChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int)));
|
connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainDialog::showFirstRunDialog()
|
bool Launcher::MainDialog::showFirstRunDialog()
|
||||||
{
|
{
|
||||||
QStringList iniPaths;
|
QStringList iniPaths;
|
||||||
|
|
||||||
|
@ -261,19 +262,11 @@ bool MainDialog::showFirstRunDialog()
|
||||||
// Add a new profile
|
// Add a new profile
|
||||||
if (msgBox.isChecked()) {
|
if (msgBox.isChecked()) {
|
||||||
mLauncherSettings.setValue(QString("Profiles/currentprofile"), QString("Imported"));
|
mLauncherSettings.setValue(QString("Profiles/currentprofile"), QString("Imported"));
|
||||||
|
mLauncherSettings.remove(QString("Profiles/Imported/content"));
|
||||||
|
|
||||||
mLauncherSettings.remove(QString("Profiles/Imported/master"));
|
QStringList contents = mGameSettings.values(QString("content"));
|
||||||
mLauncherSettings.remove(QString("Profiles/Imported/plugin"));
|
foreach (const QString &content, contents) {
|
||||||
|
mLauncherSettings.setMultiValue(QString("Profiles/Imported/content"), content);
|
||||||
QStringList masters = mGameSettings.values(QString("master"));
|
|
||||||
QStringList plugins = mGameSettings.values(QString("plugin"));
|
|
||||||
|
|
||||||
foreach (const QString &master, masters) {
|
|
||||||
mLauncherSettings.setMultiValue(QString("Profiles/Imported/master"), master);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const QString &plugin, plugins) {
|
|
||||||
mLauncherSettings.setMultiValue(QString("Profiles/Imported/plugin"), plugin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +275,7 @@ bool MainDialog::showFirstRunDialog()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainDialog::setup()
|
bool Launcher::MainDialog::setup()
|
||||||
{
|
{
|
||||||
if (!setupLauncherSettings())
|
if (!setupLauncherSettings())
|
||||||
return false;
|
return false;
|
||||||
|
@ -311,15 +304,33 @@ bool MainDialog::setup()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous)
|
void Launcher::MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous)
|
||||||
{
|
{
|
||||||
if (!current)
|
if (!current)
|
||||||
current = previous;
|
current = previous;
|
||||||
|
|
||||||
pagesWidget->setCurrentIndex(iconWidget->row(current));
|
int currentIndex = iconWidget->row(current);
|
||||||
|
int previousIndex = iconWidget->row(previous);
|
||||||
|
|
||||||
|
pagesWidget->setCurrentIndex(currentIndex);
|
||||||
|
|
||||||
|
DataFilesPage *previousPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(previousIndex));
|
||||||
|
DataFilesPage *currentPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(currentIndex));
|
||||||
|
|
||||||
|
//special call to update/save data files page list view when it's displayed/hidden.
|
||||||
|
if (previousPage)
|
||||||
|
{
|
||||||
|
if (previousPage->objectName() == "DataFilesPage")
|
||||||
|
previousPage->saveSettings();
|
||||||
|
}
|
||||||
|
else if (currentPage)
|
||||||
|
{
|
||||||
|
if (currentPage->objectName() == "DataFilesPage")
|
||||||
|
currentPage->loadSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainDialog::setupLauncherSettings()
|
bool Launcher::MainDialog::setupLauncherSettings()
|
||||||
{
|
{
|
||||||
mLauncherSettings.setMultiValueEnabled(true);
|
mLauncherSettings.setMultiValueEnabled(true);
|
||||||
|
|
||||||
|
@ -356,7 +367,7 @@ bool MainDialog::setupLauncherSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
bool expansions(UnshieldThread& cd)
|
bool Launcher::expansions(Launcher::UnshieldThread& cd)
|
||||||
{
|
{
|
||||||
if(cd.BloodmoonDone())
|
if(cd.BloodmoonDone())
|
||||||
{
|
{
|
||||||
|
@ -427,7 +438,7 @@ bool expansions(UnshieldThread& cd)
|
||||||
}
|
}
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
bool MainDialog::setupGameSettings()
|
bool Launcher::MainDialog::setupGameSettings()
|
||||||
{
|
{
|
||||||
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
|
||||||
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
||||||
|
@ -467,7 +478,7 @@ bool MainDialog::setupGameSettings()
|
||||||
foreach (const QString path, mGameSettings.getDataDirs()) {
|
foreach (const QString path, mGameSettings.getDataDirs()) {
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
filters << "*.esp" << "*.esm";
|
filters << "*.esp" << "*.esm" << "*.omwgame" << "*.omwaddon";
|
||||||
|
|
||||||
if (!dir.entryList(filters).isEmpty())
|
if (!dir.entryList(filters).isEmpty())
|
||||||
dataDirs.append(path);
|
dataDirs.append(path);
|
||||||
|
@ -550,7 +561,7 @@ bool MainDialog::setupGameSettings()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainDialog::setupGraphicsSettings()
|
bool Launcher::MainDialog::setupGraphicsSettings()
|
||||||
{
|
{
|
||||||
mGraphicsSettings.setMultiValueEnabled(false);
|
mGraphicsSettings.setMultiValueEnabled(false);
|
||||||
|
|
||||||
|
@ -604,7 +615,7 @@ bool MainDialog::setupGraphicsSettings()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::loadSettings()
|
void Launcher::MainDialog::loadSettings()
|
||||||
{
|
{
|
||||||
int width = mLauncherSettings.value(QString("General/MainWindow/width")).toInt();
|
int width = mLauncherSettings.value(QString("General/MainWindow/width")).toInt();
|
||||||
int height = mLauncherSettings.value(QString("General/MainWindow/height")).toInt();
|
int height = mLauncherSettings.value(QString("General/MainWindow/height")).toInt();
|
||||||
|
@ -616,7 +627,7 @@ void MainDialog::loadSettings()
|
||||||
move(posX, posY);
|
move(posX, posY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::saveSettings()
|
void Launcher::MainDialog::saveSettings()
|
||||||
{
|
{
|
||||||
QString width = QString::number(this->width());
|
QString width = QString::number(this->width());
|
||||||
QString height = QString::number(this->height());
|
QString height = QString::number(this->height());
|
||||||
|
@ -634,7 +645,7 @@ void MainDialog::saveSettings()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainDialog::writeSettings()
|
bool Launcher::MainDialog::writeSettings()
|
||||||
{
|
{
|
||||||
// Now write all config files
|
// Now write all config files
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
@ -727,13 +738,13 @@ bool MainDialog::writeSettings()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::closeEvent(QCloseEvent *event)
|
void Launcher::MainDialog::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
writeSettings();
|
writeSettings();
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDialog::play()
|
void Launcher::MainDialog::play()
|
||||||
{
|
{
|
||||||
if (!writeSettings()) {
|
if (!writeSettings()) {
|
||||||
qApp->quit();
|
qApp->quit();
|
||||||
|
@ -742,11 +753,11 @@ void MainDialog::play()
|
||||||
|
|
||||||
if(!mGameSettings.hasMaster()) {
|
if(!mGameSettings.hasMaster()) {
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle(tr("No master file selected"));
|
msgBox.setWindowTitle(tr("No game file selected"));
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>You do not have any master files selected.</b><br><br> \
|
msgBox.setText(tr("<br><b>You do not have no game file selected.</b><br><br> \
|
||||||
OpenMW will not start without a master file selected.<br>"));
|
OpenMW will not start without a game file selected.<br>"));
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -756,7 +767,7 @@ void MainDialog::play()
|
||||||
qApp->quit();
|
qApp->quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainDialog::startProgram(const QString &name, const QStringList &arguments, bool detached)
|
bool Launcher::MainDialog::startProgram(const QString &name, const QStringList &arguments, bool detached)
|
||||||
{
|
{
|
||||||
QString path = name;
|
QString path = name;
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
|
@ -11,57 +11,59 @@
|
||||||
|
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
class QListWidget;
|
|
||||||
class QListWidgetItem;
|
class QListWidgetItem;
|
||||||
class QStackedWidget;
|
|
||||||
class QStringList;
|
|
||||||
class QStringListModel;
|
|
||||||
class QString;
|
|
||||||
|
|
||||||
class PlayPage;
|
namespace Launcher
|
||||||
class GraphicsPage;
|
|
||||||
class DataFilesPage;
|
|
||||||
|
|
||||||
class MainDialog : public QMainWindow, private Ui::MainWindow
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class PlayPage;
|
||||||
|
class GraphicsPage;
|
||||||
public:
|
class DataFilesPage;
|
||||||
MainDialog();
|
class UnshieldThread;
|
||||||
bool setup();
|
|
||||||
bool showFirstRunDialog();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
|
|
||||||
void play();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void createIcons();
|
|
||||||
void createPages();
|
|
||||||
|
|
||||||
bool setupLauncherSettings();
|
|
||||||
bool setupGameSettings();
|
|
||||||
bool setupGraphicsSettings();
|
|
||||||
|
|
||||||
void loadSettings();
|
|
||||||
void saveSettings();
|
|
||||||
bool writeSettings();
|
|
||||||
|
|
||||||
inline bool startProgram(const QString &name, bool detached = false) { return startProgram(name, QStringList(), detached); }
|
|
||||||
bool startProgram(const QString &name, const QStringList &arguments, bool detached = false);
|
|
||||||
|
|
||||||
void closeEvent(QCloseEvent *event);
|
|
||||||
|
|
||||||
PlayPage *mPlayPage;
|
|
||||||
GraphicsPage *mGraphicsPage;
|
|
||||||
DataFilesPage *mDataFilesPage;
|
|
||||||
|
|
||||||
Files::ConfigurationManager mCfgMgr;
|
|
||||||
|
|
||||||
GameSettings mGameSettings;
|
|
||||||
GraphicsSettings mGraphicsSettings;
|
|
||||||
LauncherSettings mLauncherSettings;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
bool expansions(Launcher::UnshieldThread& cd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class MainDialog : public QMainWindow, private Ui::MainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainDialog(QWidget *parent = 0);
|
||||||
|
bool setup();
|
||||||
|
bool showFirstRunDialog();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
|
||||||
|
void play();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createIcons();
|
||||||
|
void createPages();
|
||||||
|
|
||||||
|
bool setupLauncherSettings();
|
||||||
|
bool setupGameSettings();
|
||||||
|
bool setupGraphicsSettings();
|
||||||
|
|
||||||
|
void loadSettings();
|
||||||
|
void saveSettings();
|
||||||
|
bool writeSettings();
|
||||||
|
|
||||||
|
inline bool startProgram(const QString &name, bool detached = false) { return startProgram(name, QStringList(), detached); }
|
||||||
|
bool startProgram(const QString &name, const QStringList &arguments, bool detached = false);
|
||||||
|
|
||||||
|
void closeEvent(QCloseEvent *event);
|
||||||
|
|
||||||
|
PlayPage *mPlayPage;
|
||||||
|
GraphicsPage *mGraphicsPage;
|
||||||
|
DataFilesPage *mDataFilesPage;
|
||||||
|
|
||||||
|
Files::ConfigurationManager mCfgMgr;
|
||||||
|
|
||||||
|
GameSettings mGameSettings;
|
||||||
|
GraphicsSettings mGraphicsSettings;
|
||||||
|
LauncherSettings mLauncherSettings;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
#include <QPlastiqueStyle>
|
#include <QPlastiqueStyle>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
|
Launcher::PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
|
setObjectName ("PlayPage");
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
// Hacks to get the stylesheet look properly
|
// Hacks to get the stylesheet look properly
|
||||||
|
@ -17,27 +18,22 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
|
||||||
#endif
|
#endif
|
||||||
profilesComboBox->setView(new QListView());
|
profilesComboBox->setView(new QListView());
|
||||||
|
|
||||||
connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
|
connect(profilesComboBox, SIGNAL(activated(int)), this, SIGNAL (signalProfileChanged(int)));
|
||||||
connect(playButton, SIGNAL(clicked()), this, SLOT(slotPlayClicked()));
|
connect(playButton, SIGNAL(clicked()), this, SLOT(slotPlayClicked()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayPage::setProfilesComboBoxModel(QAbstractItemModel *model)
|
void Launcher::PlayPage::setProfilesModel(QAbstractItemModel *model)
|
||||||
{
|
{
|
||||||
profilesComboBox->setModel(model);
|
profilesComboBox->setModel(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayPage::setProfilesComboBoxIndex(int index)
|
void Launcher::PlayPage::setProfilesIndex(int index)
|
||||||
{
|
{
|
||||||
profilesComboBox->setCurrentIndex(index);
|
profilesComboBox->setCurrentIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayPage::slotCurrentIndexChanged(int index)
|
void Launcher::PlayPage::slotPlayClicked()
|
||||||
{
|
|
||||||
emit profileChanged(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayPage::slotPlayClicked()
|
|
||||||
{
|
{
|
||||||
emit playButtonClicked();
|
emit playButtonClicked();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,27 +9,28 @@ class QComboBox;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
|
||||||
class PlayPage : public QWidget, private Ui::PlayPage
|
namespace Launcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class PlayPage : public QWidget, private Ui::PlayPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlayPage(QWidget *parent = 0);
|
PlayPage(QWidget *parent = 0);
|
||||||
void setProfilesComboBoxModel(QAbstractItemModel *model);
|
void setProfilesModel(QAbstractItemModel *model);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void profileChanged(int index);
|
void signalProfileChanged(int index);
|
||||||
void playButtonClicked();
|
void playButtonClicked();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setProfilesComboBoxIndex(int index);
|
void setProfilesIndex(int index);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void slotCurrentIndexChanged(int index);
|
void slotPlayClicked();
|
||||||
void slotPlayClicked();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
||||||
*/
|
*/
|
||||||
|
@ -26,16 +27,16 @@ namespace boost
|
||||||
#endif /* (BOOST_VERSION <= 104600) */
|
#endif /* (BOOST_VERSION <= 104600) */
|
||||||
|
|
||||||
|
|
||||||
GameSettings::GameSettings(Files::ConfigurationManager &cfg)
|
Launcher::GameSettings::GameSettings(Files::ConfigurationManager &cfg)
|
||||||
: mCfgMgr(cfg)
|
: mCfgMgr(cfg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GameSettings::~GameSettings()
|
Launcher::GameSettings::~GameSettings()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameSettings::validatePaths()
|
void Launcher::GameSettings::validatePaths()
|
||||||
{
|
{
|
||||||
if (mSettings.isEmpty() || !mDataDirs.isEmpty())
|
if (mSettings.isEmpty() || !mDataDirs.isEmpty())
|
||||||
return; // Don't re-validate paths if they are already parsed
|
return; // Don't re-validate paths if they are already parsed
|
||||||
|
@ -81,14 +82,14 @@ void GameSettings::validatePaths()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GameSettings::values(const QString &key, const QStringList &defaultValues)
|
QStringList Launcher::GameSettings::values(const QString &key, const QStringList &defaultValues)
|
||||||
{
|
{
|
||||||
if (!mSettings.values(key).isEmpty())
|
if (!mSettings.values(key).isEmpty())
|
||||||
return mSettings.values(key);
|
return mSettings.values(key);
|
||||||
return defaultValues;
|
return defaultValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameSettings::readFile(QTextStream &stream)
|
bool Launcher::GameSettings::readFile(QTextStream &stream)
|
||||||
{
|
{
|
||||||
QMap<QString, QString> cache;
|
QMap<QString, QString> cache;
|
||||||
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
|
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
|
||||||
|
@ -130,7 +131,7 @@ bool GameSettings::readFile(QTextStream &stream)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameSettings::writeFile(QTextStream &stream)
|
bool Launcher::GameSettings::writeFile(QTextStream &stream)
|
||||||
{
|
{
|
||||||
// Iterate in reverse order to preserve insertion order
|
// Iterate in reverse order to preserve insertion order
|
||||||
QMapIterator<QString, QString> i(mSettings);
|
QMapIterator<QString, QString> i(mSettings);
|
||||||
|
@ -139,13 +140,13 @@ bool GameSettings::writeFile(QTextStream &stream)
|
||||||
while (i.hasPrevious()) {
|
while (i.hasPrevious()) {
|
||||||
i.previous();
|
i.previous();
|
||||||
|
|
||||||
if (i.key() == QLatin1String("master") || i.key() == QLatin1String("plugin"))
|
if (i.key() == QLatin1String("content"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Quote paths with spaces
|
// Quote paths with spaces
|
||||||
if (i.key() == QLatin1String("data")
|
if (i.key() == QLatin1String("data")
|
||||||
|| i.key() == QLatin1String("data-local")
|
|| i.key() == QLatin1String("data-local")
|
||||||
|| i.key() == QLatin1String("resources"))
|
|| i.key() == QLatin1String("resources"))
|
||||||
{
|
{
|
||||||
if (i.value().contains(QChar(' ')))
|
if (i.value().contains(QChar(' ')))
|
||||||
{
|
{
|
||||||
|
@ -161,15 +162,24 @@ bool GameSettings::writeFile(QTextStream &stream)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList masters = mSettings.values(QString("master"));
|
QStringList content = mSettings.values(QString("content"));
|
||||||
for (int i = masters.count(); i--;) {
|
for (int i = content.count(); i--;) {
|
||||||
stream << "master=" << masters.at(i) << "\n";
|
stream << "content=" << content.at(i) << "\n";
|
||||||
}
|
|
||||||
|
|
||||||
QStringList plugins = mSettings.values(QString("plugin"));
|
|
||||||
for (int i = plugins.count(); i--;) {
|
|
||||||
stream << "plugin=" << plugins.at(i) << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Launcher::GameSettings::hasMaster()
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
QStringList content = mSettings.values(QString("content"));
|
||||||
|
for (int i = 0; i < content.count(); ++i) {
|
||||||
|
if (content.at(i).contains(".omwgame") || content.at(i).contains(".esm")) {
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -8,55 +8,61 @@
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
namespace Files { typedef std::vector<boost::filesystem::path> PathContainer;
|
namespace Files
|
||||||
struct ConfigurationManager;}
|
|
||||||
|
|
||||||
class GameSettings
|
|
||||||
{
|
{
|
||||||
public:
|
typedef std::vector<boost::filesystem::path> PathContainer;
|
||||||
GameSettings(Files::ConfigurationManager &cfg);
|
struct ConfigurationManager;
|
||||||
~GameSettings();
|
}
|
||||||
|
|
||||||
inline QString value(const QString &key, const QString &defaultValue = QString())
|
namespace Launcher
|
||||||
|
{
|
||||||
|
class GameSettings
|
||||||
{
|
{
|
||||||
return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key);
|
public:
|
||||||
}
|
GameSettings(Files::ConfigurationManager &cfg);
|
||||||
|
~GameSettings();
|
||||||
|
|
||||||
|
inline QString value(const QString &key, const QString &defaultValue = QString())
|
||||||
|
{
|
||||||
|
return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void setValue(const QString &key, const QString &value)
|
inline void setValue(const QString &key, const QString &value)
|
||||||
{
|
{
|
||||||
mSettings.insert(key, value);
|
mSettings.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setMultiValue(const QString &key, const QString &value)
|
inline void setMultiValue(const QString &key, const QString &value)
|
||||||
{
|
{
|
||||||
QStringList values = mSettings.values(key);
|
QStringList values = mSettings.values(key);
|
||||||
if (!values.contains(value))
|
if (!values.contains(value))
|
||||||
mSettings.insertMulti(key, value);
|
mSettings.insertMulti(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void remove(const QString &key)
|
inline void remove(const QString &key)
|
||||||
{
|
{
|
||||||
mSettings.remove(key);
|
mSettings.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QStringList getDataDirs() { return mDataDirs; }
|
inline QStringList getDataDirs() { return mDataDirs; }
|
||||||
inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); }
|
inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); }
|
||||||
inline QString getDataLocal() {return mDataLocal; }
|
inline QString getDataLocal() {return mDataLocal; }
|
||||||
inline bool hasMaster() { return mSettings.count(QString("master")) > 0; }
|
|
||||||
|
|
||||||
QStringList values(const QString &key, const QStringList &defaultValues = QStringList());
|
bool hasMaster();
|
||||||
bool readFile(QTextStream &stream);
|
|
||||||
bool writeFile(QTextStream &stream);
|
|
||||||
|
|
||||||
private:
|
QStringList values(const QString &key, const QStringList &defaultValues = QStringList());
|
||||||
Files::ConfigurationManager &mCfgMgr;
|
bool readFile(QTextStream &stream);
|
||||||
|
bool writeFile(QTextStream &stream);
|
||||||
|
|
||||||
void validatePaths();
|
private:
|
||||||
QMap<QString, QString> mSettings;
|
Files::ConfigurationManager &mCfgMgr;
|
||||||
|
|
||||||
QStringList mDataDirs;
|
void validatePaths();
|
||||||
QString mDataLocal;
|
QMap<QString, QString> mSettings;
|
||||||
};
|
|
||||||
|
|
||||||
|
QStringList mDataDirs;
|
||||||
|
QString mDataLocal;
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif // GAMESETTINGS_HPP
|
#endif // GAMESETTINGS_HPP
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
GraphicsSettings::GraphicsSettings()
|
Launcher::GraphicsSettings::GraphicsSettings()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsSettings::~GraphicsSettings()
|
Launcher::GraphicsSettings::~GraphicsSettings()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsSettings::writeFile(QTextStream &stream)
|
bool Launcher::GraphicsSettings::writeFile(QTextStream &stream)
|
||||||
{
|
{
|
||||||
QString sectionPrefix;
|
QString sectionPrefix;
|
||||||
QRegExp sectionRe("([^/]+)/(.+)$");
|
QRegExp sectionRe("([^/]+)/(.+)$");
|
||||||
|
|
|
@ -3,14 +3,16 @@
|
||||||
|
|
||||||
#include "settingsbase.hpp"
|
#include "settingsbase.hpp"
|
||||||
|
|
||||||
class GraphicsSettings : public SettingsBase<QMap<QString, QString> >
|
namespace Launcher
|
||||||
{
|
{
|
||||||
public:
|
class GraphicsSettings : public SettingsBase<QMap<QString, QString> >
|
||||||
GraphicsSettings();
|
{
|
||||||
~GraphicsSettings();
|
public:
|
||||||
|
GraphicsSettings();
|
||||||
|
~GraphicsSettings();
|
||||||
|
|
||||||
bool writeFile(QTextStream &stream);
|
bool writeFile(QTextStream &stream);
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif // GRAPHICSSETTINGS_HPP
|
#endif // GRAPHICSSETTINGS_HPP
|
||||||
|
|
|
@ -5,15 +5,17 @@
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
LauncherSettings::LauncherSettings()
|
#include <QDebug>
|
||||||
|
|
||||||
|
Launcher::LauncherSettings::LauncherSettings()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherSettings::~LauncherSettings()
|
Launcher::LauncherSettings::~LauncherSettings()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList LauncherSettings::values(const QString &key, Qt::MatchFlags flags)
|
QStringList Launcher::LauncherSettings::values(const QString &key, Qt::MatchFlags flags)
|
||||||
{
|
{
|
||||||
QMap<QString, QString> settings = SettingsBase::getSettings();
|
QMap<QString, QString> settings = SettingsBase::getSettings();
|
||||||
|
|
||||||
|
@ -34,7 +36,7 @@ QStringList LauncherSettings::values(const QString &key, Qt::MatchFlags flags)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList LauncherSettings::subKeys(const QString &key)
|
QStringList Launcher::LauncherSettings::subKeys(const QString &key)
|
||||||
{
|
{
|
||||||
QMap<QString, QString> settings = SettingsBase::getSettings();
|
QMap<QString, QString> settings = SettingsBase::getSettings();
|
||||||
QStringList keys = settings.uniqueKeys();
|
QStringList keys = settings.uniqueKeys();
|
||||||
|
@ -44,12 +46,9 @@ QStringList LauncherSettings::subKeys(const QString &key)
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
|
||||||
foreach (const QString ¤tKey, keys) {
|
foreach (const QString ¤tKey, keys) {
|
||||||
|
|
||||||
if (keyRe.indexIn(currentKey) != -1) {
|
if (keyRe.indexIn(currentKey) != -1) {
|
||||||
|
|
||||||
QString prefixedKey = keyRe.cap(1);
|
QString prefixedKey = keyRe.cap(1);
|
||||||
if(prefixedKey.startsWith(key)) {
|
if(prefixedKey.startsWith(key)) {
|
||||||
|
|
||||||
QString subKey = prefixedKey.remove(key);
|
QString subKey = prefixedKey.remove(key);
|
||||||
if (!subKey.isEmpty())
|
if (!subKey.isEmpty())
|
||||||
result.append(subKey);
|
result.append(subKey);
|
||||||
|
@ -61,7 +60,7 @@ QStringList LauncherSettings::subKeys(const QString &key)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LauncherSettings::writeFile(QTextStream &stream)
|
bool Launcher::LauncherSettings::writeFile(QTextStream &stream)
|
||||||
{
|
{
|
||||||
QString sectionPrefix;
|
QString sectionPrefix;
|
||||||
QRegExp sectionRe("([^/]+)/(.+)$");
|
QRegExp sectionRe("([^/]+)/(.+)$");
|
||||||
|
|
|
@ -3,17 +3,19 @@
|
||||||
|
|
||||||
#include "settingsbase.hpp"
|
#include "settingsbase.hpp"
|
||||||
|
|
||||||
class LauncherSettings : public SettingsBase<QMap<QString, QString> >
|
namespace Launcher
|
||||||
{
|
{
|
||||||
public:
|
class LauncherSettings : public SettingsBase<QMap<QString, QString> >
|
||||||
LauncherSettings();
|
{
|
||||||
~LauncherSettings();
|
public:
|
||||||
|
LauncherSettings();
|
||||||
|
~LauncherSettings();
|
||||||
|
|
||||||
QStringList subKeys(const QString &key);
|
QStringList subKeys(const QString &key);
|
||||||
QStringList values(const QString &key, Qt::MatchFlags flags = Qt::MatchExactly);
|
QStringList values(const QString &key, Qt::MatchFlags flags = Qt::MatchExactly);
|
||||||
|
|
||||||
bool writeFile(QTextStream &stream);
|
bool writeFile(QTextStream &stream);
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif // LAUNCHERSETTINGS_HPP
|
#endif // LAUNCHERSETTINGS_HPP
|
||||||
|
|
|
@ -7,103 +7,105 @@
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
template <class Map>
|
namespace Launcher
|
||||||
class SettingsBase
|
|
||||||
{
|
{
|
||||||
|
template <class Map>
|
||||||
public:
|
class SettingsBase
|
||||||
SettingsBase() { mMultiValue = false; }
|
|
||||||
~SettingsBase() {}
|
|
||||||
|
|
||||||
inline QString value(const QString &key, const QString &defaultValue = QString())
|
|
||||||
{
|
{
|
||||||
return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setValue(const QString &key, const QString &value)
|
public:
|
||||||
{
|
SettingsBase() { mMultiValue = false; }
|
||||||
QStringList values = mSettings.values(key);
|
~SettingsBase() {}
|
||||||
if (!values.contains(value))
|
|
||||||
mSettings.insert(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setMultiValue(const QString &key, const QString &value)
|
inline QString value(const QString &key, const QString &defaultValue = QString())
|
||||||
{
|
{
|
||||||
QStringList values = mSettings.values(key);
|
return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key);
|
||||||
if (!values.contains(value))
|
}
|
||||||
mSettings.insertMulti(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setMultiValueEnabled(bool enable)
|
inline void setValue(const QString &key, const QString &value)
|
||||||
{
|
{
|
||||||
mMultiValue = enable;
|
QStringList values = mSettings.values(key);
|
||||||
}
|
if (!values.contains(value))
|
||||||
|
mSettings.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
inline void remove(const QString &key)
|
inline void setMultiValue(const QString &key, const QString &value)
|
||||||
{
|
{
|
||||||
mSettings.remove(key);
|
QStringList values = mSettings.values(key);
|
||||||
}
|
if (!values.contains(value))
|
||||||
|
mSettings.insertMulti(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
Map getSettings() {return mSettings;}
|
inline void setMultiValueEnabled(bool enable)
|
||||||
|
{
|
||||||
|
mMultiValue = enable;
|
||||||
|
}
|
||||||
|
|
||||||
bool readFile(QTextStream &stream)
|
inline void remove(const QString &key)
|
||||||
{
|
{
|
||||||
mCache.clear();
|
mSettings.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
QString sectionPrefix;
|
Map getSettings() {return mSettings;}
|
||||||
|
|
||||||
QRegExp sectionRe("^\\[([^]]+)\\]");
|
bool readFile(QTextStream &stream)
|
||||||
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
|
{
|
||||||
|
mCache.clear();
|
||||||
|
|
||||||
while (!stream.atEnd()) {
|
QString sectionPrefix;
|
||||||
QString line = stream.readLine();
|
|
||||||
|
|
||||||
if (line.isEmpty() || line.startsWith("#"))
|
QRegExp sectionRe("^\\[([^]]+)\\]");
|
||||||
continue;
|
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
|
||||||
|
|
||||||
if (sectionRe.exactMatch(line)) {
|
while (!stream.atEnd()) {
|
||||||
sectionPrefix = sectionRe.cap(1);
|
QString line = stream.readLine();
|
||||||
sectionPrefix.append("/");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyRe.indexIn(line) != -1) {
|
if (line.isEmpty() || line.startsWith("#"))
|
||||||
|
continue;
|
||||||
|
|
||||||
QString key = keyRe.cap(1).trimmed();
|
if (sectionRe.exactMatch(line)) {
|
||||||
QString value = keyRe.cap(2).trimmed();
|
sectionPrefix = sectionRe.cap(1);
|
||||||
|
sectionPrefix.append("/");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!sectionPrefix.isEmpty())
|
if (keyRe.indexIn(line) != -1) {
|
||||||
key.prepend(sectionPrefix);
|
|
||||||
|
|
||||||
mSettings.remove(key);
|
QString key = keyRe.cap(1).trimmed();
|
||||||
|
QString value = keyRe.cap(2).trimmed();
|
||||||
|
|
||||||
QStringList values = mCache.values(key);
|
if (!sectionPrefix.isEmpty())
|
||||||
|
key.prepend(sectionPrefix);
|
||||||
|
|
||||||
if (!values.contains(value)) {
|
mSettings.remove(key);
|
||||||
if (mMultiValue) {
|
|
||||||
mCache.insertMulti(key, value);
|
QStringList values = mCache.values(key);
|
||||||
} else {
|
|
||||||
mCache.insert(key, value);
|
if (!values.contains(value)) {
|
||||||
|
if (mMultiValue) {
|
||||||
|
mCache.insertMulti(key, value);
|
||||||
|
} else {
|
||||||
|
mCache.insert(key, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (mSettings.isEmpty()) {
|
if (mSettings.isEmpty()) {
|
||||||
mSettings = mCache; // This is the first time we read a file
|
mSettings = mCache; // This is the first time we read a file
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge the changed keys with those which didn't
|
||||||
|
mSettings.unite(mCache);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the changed keys with those which didn't
|
private:
|
||||||
mSettings.unite(mCache);
|
Map mSettings;
|
||||||
return true;
|
Map mCache;
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Map mSettings;
|
|
||||||
Map mCache;
|
|
||||||
|
|
||||||
bool mMultiValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
bool mMultiValue;
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif // SETTINGSBASE_HPP
|
#endif // SETTINGSBASE_HPP
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "textslotmsgbox.hpp"
|
#include "textslotmsgbox.hpp"
|
||||||
|
|
||||||
void TextSlotMsgBox::setTextSlot(const QString& string)
|
void Launcher::TextSlotMsgBox::setTextSlot(const QString& string)
|
||||||
{
|
{
|
||||||
setText(string);
|
setText(string);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
class TextSlotMsgBox : public QMessageBox
|
namespace Launcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class TextSlotMsgBox : public QMessageBox
|
||||||
public slots:
|
{
|
||||||
void setTextSlot(const QString& string);
|
Q_OBJECT
|
||||||
};
|
public slots:
|
||||||
|
void setTextSlot(const QString& string);
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -292,30 +292,30 @@ namespace
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnshieldThread::SetMorrowindPath(const std::string& path)
|
bool Launcher::UnshieldThread::SetMorrowindPath(const std::string& path)
|
||||||
{
|
{
|
||||||
mMorrowindPath = path;
|
mMorrowindPath = path;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnshieldThread::SetTribunalPath(const std::string& path)
|
bool Launcher::UnshieldThread::SetTribunalPath(const std::string& path)
|
||||||
{
|
{
|
||||||
mTribunalPath = path;
|
mTribunalPath = path;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnshieldThread::SetBloodmoonPath(const std::string& path)
|
bool Launcher::UnshieldThread::SetBloodmoonPath(const std::string& path)
|
||||||
{
|
{
|
||||||
mBloodmoonPath = path;
|
mBloodmoonPath = path;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnshieldThread::SetOutputPath(const std::string& path)
|
void Launcher::UnshieldThread::SetOutputPath(const std::string& path)
|
||||||
{
|
{
|
||||||
mOutputPath = path;
|
mOutputPath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnshieldThread::extract_file(Unshield* unshield, bfs::path output_dir, const char* prefix, int index)
|
bool Launcher::UnshieldThread::extract_file(Unshield* unshield, bfs::path output_dir, const char* prefix, int index)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
bfs::path dirname;
|
bfs::path dirname;
|
||||||
|
@ -349,7 +349,7 @@ bool UnshieldThread::extract_file(Unshield* unshield, bfs::path output_dir, cons
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnshieldThread::extract_cab(const bfs::path& cab, const bfs::path& output_dir, bool extract_ini)
|
void Launcher::UnshieldThread::extract_cab(const bfs::path& cab, const bfs::path& output_dir, bool extract_ini)
|
||||||
{
|
{
|
||||||
Unshield * unshield;
|
Unshield * unshield;
|
||||||
unshield = unshield_open(cab.c_str());
|
unshield = unshield_open(cab.c_str());
|
||||||
|
@ -369,7 +369,7 @@ void UnshieldThread::extract_cab(const bfs::path& cab, const bfs::path& output_d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool UnshieldThread::extract()
|
bool Launcher::UnshieldThread::extract()
|
||||||
{
|
{
|
||||||
bfs::path outputDataFilesDir = mOutputPath;
|
bfs::path outputDataFilesDir = mOutputPath;
|
||||||
outputDataFilesDir /= "Data Files";
|
outputDataFilesDir /= "Data Files";
|
||||||
|
@ -475,7 +475,7 @@ bool UnshieldThread::extract()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnshieldThread::Done()
|
void Launcher::UnshieldThread::Done()
|
||||||
{
|
{
|
||||||
// Get rid of unnecessary files
|
// Get rid of unnecessary files
|
||||||
bfs::remove_all(mOutputPath / "extract-temp");
|
bfs::remove_all(mOutputPath / "extract-temp");
|
||||||
|
@ -491,28 +491,28 @@ void UnshieldThread::Done()
|
||||||
bfs::last_write_time(findFile(mOutputPath, "bloodmoon.esm"), getTime("3 June 2003"));
|
bfs::last_write_time(findFile(mOutputPath, "bloodmoon.esm"), getTime("3 June 2003"));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UnshieldThread::GetMWEsmPath()
|
std::string Launcher::UnshieldThread::GetMWEsmPath()
|
||||||
{
|
{
|
||||||
return findFile(mOutputPath / "Data Files", "morrowind.esm").string();
|
return findFile(mOutputPath / "Data Files", "morrowind.esm").string();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnshieldThread::TribunalDone()
|
bool Launcher::UnshieldThread::TribunalDone()
|
||||||
{
|
{
|
||||||
return mTribunalDone;
|
return mTribunalDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnshieldThread::BloodmoonDone()
|
bool Launcher::UnshieldThread::BloodmoonDone()
|
||||||
{
|
{
|
||||||
return mBloodmoonDone;
|
return mBloodmoonDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnshieldThread::run()
|
void Launcher::UnshieldThread::run()
|
||||||
{
|
{
|
||||||
extract();
|
extract();
|
||||||
emit close();
|
emit close();
|
||||||
}
|
}
|
||||||
|
|
||||||
UnshieldThread::UnshieldThread()
|
Launcher::UnshieldThread::UnshieldThread()
|
||||||
{
|
{
|
||||||
unshield_set_log_level(0);
|
unshield_set_log_level(0);
|
||||||
mMorrowindDone = false;
|
mMorrowindDone = false;
|
||||||
|
|
|
@ -7,50 +7,52 @@
|
||||||
|
|
||||||
#include <libunshield.h>
|
#include <libunshield.h>
|
||||||
|
|
||||||
class UnshieldThread : public QThread
|
namespace Launcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class UnshieldThread : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool SetMorrowindPath(const std::string& path);
|
bool SetMorrowindPath(const std::string& path);
|
||||||
bool SetTribunalPath(const std::string& path);
|
bool SetTribunalPath(const std::string& path);
|
||||||
bool SetBloodmoonPath(const std::string& path);
|
bool SetBloodmoonPath(const std::string& path);
|
||||||
|
|
||||||
void SetOutputPath(const std::string& path);
|
void SetOutputPath(const std::string& path);
|
||||||
|
|
||||||
bool extract();
|
bool extract();
|
||||||
|
|
||||||
bool TribunalDone();
|
bool TribunalDone();
|
||||||
bool BloodmoonDone();
|
bool BloodmoonDone();
|
||||||
|
|
||||||
void Done();
|
void Done();
|
||||||
|
|
||||||
std::string GetMWEsmPath();
|
std::string GetMWEsmPath();
|
||||||
|
|
||||||
UnshieldThread();
|
UnshieldThread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void extract_cab(const boost::filesystem::path& cab, const boost::filesystem::path& output_dir, bool extract_ini = false);
|
void extract_cab(const boost::filesystem::path& cab, const boost::filesystem::path& output_dir, bool extract_ini = false);
|
||||||
bool extract_file(Unshield* unshield, boost::filesystem::path output_dir, const char* prefix, int index);
|
bool extract_file(Unshield* unshield, boost::filesystem::path output_dir, const char* prefix, int index);
|
||||||
|
|
||||||
boost::filesystem::path mMorrowindPath;
|
boost::filesystem::path mMorrowindPath;
|
||||||
boost::filesystem::path mTribunalPath;
|
boost::filesystem::path mTribunalPath;
|
||||||
boost::filesystem::path mBloodmoonPath;
|
boost::filesystem::path mBloodmoonPath;
|
||||||
|
|
||||||
bool mMorrowindDone;
|
bool mMorrowindDone;
|
||||||
bool mTribunalDone;
|
bool mTribunalDone;
|
||||||
bool mBloodmoonDone;
|
bool mBloodmoonDone;
|
||||||
|
|
||||||
boost::filesystem::path mOutputPath;
|
boost::filesystem::path mOutputPath;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void run();
|
virtual void run();
|
||||||
|
|
||||||
signals:
|
|
||||||
void signalGUI(QString);
|
|
||||||
void close();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void signalGUI(QString);
|
||||||
|
void close();
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -54,72 +54,61 @@
|
||||||
Emulates the QMessageBox API with
|
Emulates the QMessageBox API with
|
||||||
static conveniences. The message label can open external URLs.
|
static conveniences. The message label can open external URLs.
|
||||||
*/
|
*/
|
||||||
|
Launcher::CheckableMessageBoxPrivate::CheckableMessageBoxPrivate(QDialog *q)
|
||||||
class CheckableMessageBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CheckableMessageBoxPrivate(QDialog *q)
|
|
||||||
: clickedButton(0)
|
: clickedButton(0)
|
||||||
{
|
{
|
||||||
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
|
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
|
||||||
|
|
||||||
pixmapLabel = new QLabel(q);
|
pixmapLabel = new QLabel(q);
|
||||||
sizePolicy.setHorizontalStretch(0);
|
sizePolicy.setHorizontalStretch(0);
|
||||||
sizePolicy.setVerticalStretch(0);
|
sizePolicy.setVerticalStretch(0);
|
||||||
sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth());
|
sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth());
|
||||||
pixmapLabel->setSizePolicy(sizePolicy);
|
pixmapLabel->setSizePolicy(sizePolicy);
|
||||||
pixmapLabel->setVisible(false);
|
pixmapLabel->setVisible(false);
|
||||||
|
|
||||||
QSpacerItem *pixmapSpacer =
|
QSpacerItem *pixmapSpacer =
|
||||||
new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
|
new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
|
||||||
|
|
||||||
messageLabel = new QLabel(q);
|
messageLabel = new QLabel(q);
|
||||||
messageLabel->setMinimumSize(QSize(300, 0));
|
messageLabel->setMinimumSize(QSize(300, 0));
|
||||||
messageLabel->setWordWrap(true);
|
messageLabel->setWordWrap(true);
|
||||||
messageLabel->setOpenExternalLinks(true);
|
messageLabel->setOpenExternalLinks(true);
|
||||||
messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse);
|
messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse);
|
||||||
|
|
||||||
QSpacerItem *checkBoxRightSpacer =
|
QSpacerItem *checkBoxRightSpacer =
|
||||||
new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||||
QSpacerItem *buttonSpacer =
|
QSpacerItem *buttonSpacer =
|
||||||
new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum);
|
new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||||
|
|
||||||
checkBox = new QCheckBox(q);
|
checkBox = new QCheckBox(q);
|
||||||
checkBox->setText(CheckableMessageBox::tr("Do not ask again"));
|
checkBox->setText(Launcher::CheckableMessageBox::tr("Do not ask again"));
|
||||||
|
|
||||||
buttonBox = new QDialogButtonBox(q);
|
buttonBox = new QDialogButtonBox(q);
|
||||||
buttonBox->setOrientation(Qt::Horizontal);
|
buttonBox->setOrientation(Qt::Horizontal);
|
||||||
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
||||||
|
|
||||||
QVBoxLayout *verticalLayout = new QVBoxLayout();
|
QVBoxLayout *verticalLayout = new QVBoxLayout();
|
||||||
verticalLayout->addWidget(pixmapLabel);
|
verticalLayout->addWidget(pixmapLabel);
|
||||||
verticalLayout->addItem(pixmapSpacer);
|
verticalLayout->addItem(pixmapSpacer);
|
||||||
|
|
||||||
QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
|
QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
|
||||||
horizontalLayout_2->addLayout(verticalLayout);
|
horizontalLayout_2->addLayout(verticalLayout);
|
||||||
horizontalLayout_2->addWidget(messageLabel);
|
horizontalLayout_2->addWidget(messageLabel);
|
||||||
|
|
||||||
QHBoxLayout *horizontalLayout = new QHBoxLayout();
|
QHBoxLayout *horizontalLayout = new QHBoxLayout();
|
||||||
horizontalLayout->addWidget(checkBox);
|
horizontalLayout->addWidget(checkBox);
|
||||||
horizontalLayout->addItem(checkBoxRightSpacer);
|
horizontalLayout->addItem(checkBoxRightSpacer);
|
||||||
|
|
||||||
QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q);
|
QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q);
|
||||||
verticalLayout_2->addLayout(horizontalLayout_2);
|
verticalLayout_2->addLayout(horizontalLayout_2);
|
||||||
verticalLayout_2->addLayout(horizontalLayout);
|
verticalLayout_2->addLayout(horizontalLayout);
|
||||||
verticalLayout_2->addItem(buttonSpacer);
|
verticalLayout_2->addItem(buttonSpacer);
|
||||||
verticalLayout_2->addWidget(buttonBox);
|
verticalLayout_2->addWidget(buttonBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
QLabel *pixmapLabel;
|
Launcher::CheckableMessageBox::CheckableMessageBox(QWidget *parent) :
|
||||||
QLabel *messageLabel;
|
|
||||||
QCheckBox *checkBox;
|
|
||||||
QDialogButtonBox *buttonBox;
|
|
||||||
QAbstractButton *clickedButton;
|
|
||||||
};
|
|
||||||
|
|
||||||
CheckableMessageBox::CheckableMessageBox(QWidget *parent) :
|
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
d(new CheckableMessageBoxPrivate(this))
|
d(new Launcher::CheckableMessageBoxPrivate(this))
|
||||||
{
|
{
|
||||||
setModal(true);
|
setModal(true);
|
||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
@ -129,102 +118,102 @@ CheckableMessageBox::CheckableMessageBox(QWidget *parent) :
|
||||||
SLOT(slotClicked(QAbstractButton*)));
|
SLOT(slotClicked(QAbstractButton*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckableMessageBox::~CheckableMessageBox()
|
Launcher::CheckableMessageBox::~CheckableMessageBox()
|
||||||
{
|
{
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableMessageBox::slotClicked(QAbstractButton *b)
|
void Launcher::CheckableMessageBox::slotClicked(QAbstractButton *b)
|
||||||
{
|
{
|
||||||
d->clickedButton = b;
|
d->clickedButton = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractButton *CheckableMessageBox::clickedButton() const
|
QAbstractButton *Launcher::CheckableMessageBox::clickedButton() const
|
||||||
{
|
{
|
||||||
return d->clickedButton;
|
return d->clickedButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialogButtonBox::StandardButton CheckableMessageBox::clickedStandardButton() const
|
QDialogButtonBox::StandardButton Launcher::CheckableMessageBox::clickedStandardButton() const
|
||||||
{
|
{
|
||||||
if (d->clickedButton)
|
if (d->clickedButton)
|
||||||
return d->buttonBox->standardButton(d->clickedButton);
|
return d->buttonBox->standardButton(d->clickedButton);
|
||||||
return QDialogButtonBox::NoButton;
|
return QDialogButtonBox::NoButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CheckableMessageBox::text() const
|
QString Launcher::CheckableMessageBox::text() const
|
||||||
{
|
{
|
||||||
return d->messageLabel->text();
|
return d->messageLabel->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableMessageBox::setText(const QString &t)
|
void Launcher::CheckableMessageBox::setText(const QString &t)
|
||||||
{
|
{
|
||||||
d->messageLabel->setText(t);
|
d->messageLabel->setText(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap CheckableMessageBox::iconPixmap() const
|
QPixmap Launcher::CheckableMessageBox::iconPixmap() const
|
||||||
{
|
{
|
||||||
if (const QPixmap *p = d->pixmapLabel->pixmap())
|
if (const QPixmap *p = d->pixmapLabel->pixmap())
|
||||||
return QPixmap(*p);
|
return QPixmap(*p);
|
||||||
return QPixmap();
|
return QPixmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableMessageBox::setIconPixmap(const QPixmap &p)
|
void Launcher::CheckableMessageBox::setIconPixmap(const QPixmap &p)
|
||||||
{
|
{
|
||||||
d->pixmapLabel->setPixmap(p);
|
d->pixmapLabel->setPixmap(p);
|
||||||
d->pixmapLabel->setVisible(!p.isNull());
|
d->pixmapLabel->setVisible(!p.isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckableMessageBox::isChecked() const
|
bool Launcher::CheckableMessageBox::isChecked() const
|
||||||
{
|
{
|
||||||
return d->checkBox->isChecked();
|
return d->checkBox->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableMessageBox::setChecked(bool s)
|
void Launcher::CheckableMessageBox::setChecked(bool s)
|
||||||
{
|
{
|
||||||
d->checkBox->setChecked(s);
|
d->checkBox->setChecked(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CheckableMessageBox::checkBoxText() const
|
QString Launcher::CheckableMessageBox::checkBoxText() const
|
||||||
{
|
{
|
||||||
return d->checkBox->text();
|
return d->checkBox->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableMessageBox::setCheckBoxText(const QString &t)
|
void Launcher::CheckableMessageBox::setCheckBoxText(const QString &t)
|
||||||
{
|
{
|
||||||
d->checkBox->setText(t);
|
d->checkBox->setText(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckableMessageBox::isCheckBoxVisible() const
|
bool Launcher::CheckableMessageBox::isCheckBoxVisible() const
|
||||||
{
|
{
|
||||||
return d->checkBox->isVisible();
|
return d->checkBox->isVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableMessageBox::setCheckBoxVisible(bool v)
|
void Launcher::CheckableMessageBox::setCheckBoxVisible(bool v)
|
||||||
{
|
{
|
||||||
d->checkBox->setVisible(v);
|
d->checkBox->setVisible(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialogButtonBox::StandardButtons CheckableMessageBox::standardButtons() const
|
QDialogButtonBox::StandardButtons Launcher::CheckableMessageBox::standardButtons() const
|
||||||
{
|
{
|
||||||
return d->buttonBox->standardButtons();
|
return d->buttonBox->standardButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableMessageBox::setStandardButtons(QDialogButtonBox::StandardButtons s)
|
void Launcher::CheckableMessageBox::setStandardButtons(QDialogButtonBox::StandardButtons s)
|
||||||
{
|
{
|
||||||
d->buttonBox->setStandardButtons(s);
|
d->buttonBox->setStandardButtons(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPushButton *CheckableMessageBox::button(QDialogButtonBox::StandardButton b) const
|
QPushButton *Launcher::CheckableMessageBox::button(QDialogButtonBox::StandardButton b) const
|
||||||
{
|
{
|
||||||
return d->buttonBox->button(b);
|
return d->buttonBox->button(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPushButton *CheckableMessageBox::addButton(const QString &text, QDialogButtonBox::ButtonRole role)
|
QPushButton *Launcher::CheckableMessageBox::addButton(const QString &text, QDialogButtonBox::ButtonRole role)
|
||||||
{
|
{
|
||||||
return d->buttonBox->addButton(text, role);
|
return d->buttonBox->addButton(text, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialogButtonBox::StandardButton CheckableMessageBox::defaultButton() const
|
QDialogButtonBox::StandardButton Launcher::CheckableMessageBox::defaultButton() const
|
||||||
{
|
{
|
||||||
foreach (QAbstractButton *b, d->buttonBox->buttons())
|
foreach (QAbstractButton *b, d->buttonBox->buttons())
|
||||||
if (QPushButton *pb = qobject_cast<QPushButton *>(b))
|
if (QPushButton *pb = qobject_cast<QPushButton *>(b))
|
||||||
|
@ -233,7 +222,7 @@ QDialogButtonBox::StandardButton CheckableMessageBox::defaultButton() const
|
||||||
return QDialogButtonBox::NoButton;
|
return QDialogButtonBox::NoButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckableMessageBox::setDefaultButton(QDialogButtonBox::StandardButton s)
|
void Launcher::CheckableMessageBox::setDefaultButton(QDialogButtonBox::StandardButton s)
|
||||||
{
|
{
|
||||||
if (QPushButton *b = d->buttonBox->button(s)) {
|
if (QPushButton *b = d->buttonBox->button(s)) {
|
||||||
b->setDefault(true);
|
b->setDefault(true);
|
||||||
|
@ -242,7 +231,7 @@ void CheckableMessageBox::setDefaultButton(QDialogButtonBox::StandardButton s)
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialogButtonBox::StandardButton
|
QDialogButtonBox::StandardButton
|
||||||
CheckableMessageBox::question(QWidget *parent,
|
Launcher::CheckableMessageBox::question(QWidget *parent,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &question,
|
const QString &question,
|
||||||
const QString &checkBoxText,
|
const QString &checkBoxText,
|
||||||
|
@ -263,7 +252,7 @@ CheckableMessageBox::question(QWidget *parent,
|
||||||
return mb.clickedStandardButton();
|
return mb.clickedStandardButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
QMessageBox::StandardButton CheckableMessageBox::dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton db)
|
QMessageBox::StandardButton Launcher::CheckableMessageBox::dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton db)
|
||||||
{
|
{
|
||||||
return static_cast<QMessageBox::StandardButton>(int(db));
|
return static_cast<QMessageBox::StandardButton>(int(db));
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,67 +34,83 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
class CheckableMessageBoxPrivate;
|
class QCheckBox;
|
||||||
|
|
||||||
class CheckableMessageBox : public QDialog
|
namespace Launcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class CheckableMessageBoxPrivate
|
||||||
Q_PROPERTY(QString text READ text WRITE setText)
|
{
|
||||||
Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
|
public:
|
||||||
Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked)
|
|
||||||
Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText)
|
|
||||||
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
|
|
||||||
Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton)
|
|
||||||
|
|
||||||
public:
|
QLabel *pixmapLabel;
|
||||||
explicit CheckableMessageBox(QWidget *parent);
|
QLabel *messageLabel;
|
||||||
virtual ~CheckableMessageBox();
|
QCheckBox *checkBox;
|
||||||
|
QDialogButtonBox *buttonBox;
|
||||||
|
QAbstractButton *clickedButton;
|
||||||
|
|
||||||
static QDialogButtonBox::StandardButton
|
public:
|
||||||
question(QWidget *parent,
|
CheckableMessageBoxPrivate(QDialog *q);
|
||||||
const QString &title,
|
};
|
||||||
const QString &question,
|
|
||||||
const QString &checkBoxText,
|
|
||||||
bool *checkBoxSetting,
|
|
||||||
QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No,
|
|
||||||
QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No);
|
|
||||||
|
|
||||||
QString text() const;
|
class CheckableMessageBox : public QDialog
|
||||||
void setText(const QString &);
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString text READ text WRITE setText)
|
||||||
|
Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
|
||||||
|
Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked)
|
||||||
|
Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText)
|
||||||
|
Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons)
|
||||||
|
Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton)
|
||||||
|
|
||||||
bool isChecked() const;
|
public:
|
||||||
void setChecked(bool s);
|
explicit CheckableMessageBox(QWidget *parent);
|
||||||
|
virtual ~CheckableMessageBox();
|
||||||
|
|
||||||
QString checkBoxText() const;
|
static QDialogButtonBox::StandardButton
|
||||||
void setCheckBoxText(const QString &);
|
question(QWidget *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &question,
|
||||||
|
const QString &checkBoxText,
|
||||||
|
bool *checkBoxSetting,
|
||||||
|
QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No,
|
||||||
|
QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No);
|
||||||
|
|
||||||
bool isCheckBoxVisible() const;
|
QString text() const;
|
||||||
void setCheckBoxVisible(bool);
|
void setText(const QString &);
|
||||||
|
|
||||||
QDialogButtonBox::StandardButtons standardButtons() const;
|
bool isChecked() const;
|
||||||
void setStandardButtons(QDialogButtonBox::StandardButtons s);
|
void setChecked(bool s);
|
||||||
QPushButton *button(QDialogButtonBox::StandardButton b) const;
|
|
||||||
QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role);
|
|
||||||
|
|
||||||
QDialogButtonBox::StandardButton defaultButton() const;
|
QString checkBoxText() const;
|
||||||
void setDefaultButton(QDialogButtonBox::StandardButton s);
|
void setCheckBoxText(const QString &);
|
||||||
|
|
||||||
// See static QMessageBox::standardPixmap()
|
bool isCheckBoxVisible() const;
|
||||||
QPixmap iconPixmap() const;
|
void setCheckBoxVisible(bool);
|
||||||
void setIconPixmap (const QPixmap &p);
|
|
||||||
|
|
||||||
// Query the result
|
QDialogButtonBox::StandardButtons standardButtons() const;
|
||||||
QAbstractButton *clickedButton() const;
|
void setStandardButtons(QDialogButtonBox::StandardButtons s);
|
||||||
QDialogButtonBox::StandardButton clickedStandardButton() const;
|
QPushButton *button(QDialogButtonBox::StandardButton b) const;
|
||||||
|
QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role);
|
||||||
|
|
||||||
// Conversion convenience
|
QDialogButtonBox::StandardButton defaultButton() const;
|
||||||
static QMessageBox::StandardButton dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton);
|
void setDefaultButton(QDialogButtonBox::StandardButton s);
|
||||||
|
|
||||||
private slots:
|
// See static QMessageBox::standardPixmap()
|
||||||
void slotClicked(QAbstractButton *b);
|
QPixmap iconPixmap() const;
|
||||||
|
void setIconPixmap (const QPixmap &p);
|
||||||
|
|
||||||
private:
|
// Query the result
|
||||||
CheckableMessageBoxPrivate *d;
|
QAbstractButton *clickedButton() const;
|
||||||
};
|
QDialogButtonBox::StandardButton clickedStandardButton() const;
|
||||||
|
|
||||||
|
// Conversion convenience
|
||||||
|
static QMessageBox::StandardButton dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void slotClicked(QAbstractButton *b);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CheckableMessageBoxPrivate *d;
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif // CHECKABLEMESSAGEBOX_HPP
|
#endif // CHECKABLEMESSAGEBOX_HPP
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#include <QToolButton>
|
|
||||||
#include <QStyle>
|
|
||||||
|
|
||||||
#include "lineedit.hpp"
|
#include "lineedit.hpp"
|
||||||
|
|
||||||
LineEdit::LineEdit(QWidget *parent)
|
LineEdit::LineEdit(QWidget *parent)
|
||||||
: QLineEdit(parent)
|
: QLineEdit(parent)
|
||||||
|
{
|
||||||
|
setupClearButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineEdit::setupClearButton()
|
||||||
{
|
{
|
||||||
mClearButton = new QToolButton(this);
|
mClearButton = new QToolButton(this);
|
||||||
QPixmap pixmap(":images/clear.png");
|
QPixmap pixmap(":images/clear.png");
|
||||||
|
@ -15,13 +17,6 @@ LineEdit::LineEdit(QWidget *parent)
|
||||||
mClearButton->hide();
|
mClearButton->hide();
|
||||||
connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
||||||
connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateClearButton(const QString&)));
|
connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateClearButton(const QString&)));
|
||||||
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
|
||||||
|
|
||||||
setObjectName(QString("LineEdit"));
|
|
||||||
setStyleSheet(QString("LineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1));
|
|
||||||
QSize msz = minimumSizeHint();
|
|
||||||
setMinimumSize(qMax(msz.width(), mClearButton->sizeHint().height() + frameWidth * 2 + 2),
|
|
||||||
qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineEdit::resizeEvent(QResizeEvent *)
|
void LineEdit::resizeEvent(QResizeEvent *)
|
|
@ -11,6 +11,9 @@
|
||||||
#define LINEEDIT_H
|
#define LINEEDIT_H
|
||||||
|
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QStylePainter>
|
||||||
|
#include <QToolButton>
|
||||||
|
|
||||||
class QToolButton;
|
class QToolButton;
|
||||||
|
|
||||||
|
@ -18,6 +21,8 @@ class LineEdit : public QLineEdit
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
QString mPlaceholderText;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LineEdit(QWidget *parent = 0);
|
LineEdit(QWidget *parent = 0);
|
||||||
|
|
||||||
|
@ -27,8 +32,10 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
void updateClearButton(const QString &text);
|
void updateClearButton(const QString &text);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
QToolButton *mClearButton;
|
QToolButton *mClearButton;
|
||||||
|
|
||||||
|
void setupClearButton();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIENEDIT_H
|
#endif // LIENEDIT_H
|
|
@ -5,18 +5,12 @@
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
#include "profilescombobox.hpp"
|
#include "profilescombobox.hpp"
|
||||||
#include "comboboxlineedit.hpp"
|
|
||||||
|
|
||||||
ProfilesComboBox::ProfilesComboBox(QWidget *parent) :
|
ProfilesComboBox::ProfilesComboBox(QWidget *parent) :
|
||||||
QComboBox(parent)
|
ContentSelectorView::ComboBox(parent)
|
||||||
{
|
{
|
||||||
mValidator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
|
connect(this, SIGNAL(activated(int)), this,
|
||||||
setEditEnabled(true);
|
SLOT(slotIndexChangedByUser(int)));
|
||||||
setValidator(mValidator);
|
|
||||||
setCompleter(0);
|
|
||||||
|
|
||||||
connect(this, SIGNAL(currentIndexChanged(int)), this,
|
|
||||||
SLOT(slotIndexChanged(int)));
|
|
||||||
|
|
||||||
setInsertPolicy(QComboBox::NoInsert);
|
setInsertPolicy(QComboBox::NoInsert);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +31,7 @@ void ProfilesComboBox::setEditEnabled(bool editable)
|
||||||
setValidator(mValidator);
|
setValidator(mValidator);
|
||||||
|
|
||||||
ComboBoxLineEdit *edit = new ComboBoxLineEdit(this);
|
ComboBoxLineEdit *edit = new ComboBoxLineEdit(this);
|
||||||
|
|
||||||
setLineEdit(edit);
|
setLineEdit(edit);
|
||||||
setCompleter(0);
|
setCompleter(0);
|
||||||
|
|
||||||
|
@ -45,6 +40,9 @@ void ProfilesComboBox::setEditEnabled(bool editable)
|
||||||
|
|
||||||
connect(lineEdit(), SIGNAL(textChanged(QString)), this,
|
connect(lineEdit(), SIGNAL(textChanged(QString)), this,
|
||||||
SLOT(slotTextChanged(QString)));
|
SLOT(slotTextChanged(QString)));
|
||||||
|
|
||||||
|
connect (lineEdit(), SIGNAL(textChanged(QString)), this,
|
||||||
|
SIGNAL (signalProfileTextChanged (QString)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilesComboBox::slotTextChanged(const QString &text)
|
void ProfilesComboBox::slotTextChanged(const QString &text)
|
||||||
|
@ -82,11 +80,20 @@ void ProfilesComboBox::slotEditingFinished()
|
||||||
emit(profileRenamed(previous, current));
|
emit(profileRenamed(previous, current));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilesComboBox::slotIndexChanged(int index)
|
void ProfilesComboBox::slotIndexChangedByUser(int index)
|
||||||
{
|
{
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
emit(profileChanged(mOldProfile, currentText()));
|
emit (signalProfileChanged(mOldProfile, currentText()));
|
||||||
mOldProfile = itemText(index);
|
mOldProfile = currentText();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilesComboBox::ComboBoxLineEdit::ComboBoxLineEdit (QWidget *parent)
|
||||||
|
: LineEdit (parent)
|
||||||
|
{
|
||||||
|
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||||
|
|
||||||
|
setObjectName(QString("ComboBoxLineEdit"));
|
||||||
|
setStyleSheet(QString("ComboBoxLineEdit { background-color: transparent; padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1));
|
||||||
}
|
}
|
47
apps/launcher/utils/profilescombobox.hpp
Normal file
47
apps/launcher/utils/profilescombobox.hpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef PROFILESCOMBOBOX_HPP
|
||||||
|
#define PROFILESCOMBOBOX_HPP
|
||||||
|
|
||||||
|
#include "components/contentselector/view/combobox.hpp"
|
||||||
|
#include "lineedit.hpp"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
class QString;
|
||||||
|
|
||||||
|
class ProfilesComboBox : public ContentSelectorView::ComboBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
class ComboBoxLineEdit : public LineEdit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ComboBoxLineEdit (QWidget *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ProfilesComboBox(QWidget *parent = 0);
|
||||||
|
void setEditEnabled(bool editable);
|
||||||
|
void setCurrentProfile(int index)
|
||||||
|
{
|
||||||
|
ComboBox::setCurrentIndex(index);
|
||||||
|
mOldProfile = currentText();
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void signalProfileTextChanged(const QString &item);
|
||||||
|
void signalProfileChanged(const QString &previous, const QString ¤t);
|
||||||
|
void signalProfileChanged(int index);
|
||||||
|
void profileRenamed(const QString &oldName, const QString &newName);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void slotEditingFinished();
|
||||||
|
void slotIndexChangedByUser(int index);
|
||||||
|
void slotTextChanged(const QString &text);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString mOldProfile;
|
||||||
|
};
|
||||||
|
#endif // PROFILESCOMBOBOX_HPP
|
|
@ -7,19 +7,18 @@
|
||||||
#include <QValidator>
|
#include <QValidator>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
|
||||||
#include <components/fileorderlist/utils/lineedit.hpp>
|
Launcher::TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWidget *parent) :
|
||||||
|
|
||||||
TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWidget *parent) :
|
|
||||||
QDialog(parent)
|
QDialog(parent)
|
||||||
{
|
{
|
||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
mButtonBox = new QDialogButtonBox(this);
|
mButtonBox = new QDialogButtonBox(this);
|
||||||
mButtonBox->addButton(QDialogButtonBox::Ok);
|
mButtonBox->addButton(QDialogButtonBox::Ok);
|
||||||
mButtonBox->addButton(QDialogButtonBox::Cancel);
|
mButtonBox->addButton(QDialogButtonBox::Cancel);
|
||||||
|
mButtonBox->button(QDialogButtonBox::Ok)->setEnabled (false);
|
||||||
|
|
||||||
// Line edit
|
// Line edit
|
||||||
QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
|
QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
|
||||||
mLineEdit = new LineEdit(this);
|
mLineEdit = new DialogLineEdit(this);
|
||||||
mLineEdit->setValidator(validator);
|
mLineEdit->setValidator(validator);
|
||||||
mLineEdit->setCompleter(0);
|
mLineEdit->setCompleter(0);
|
||||||
|
|
||||||
|
@ -38,34 +37,51 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid
|
||||||
Q_UNUSED(title);
|
Q_UNUSED(title);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setOkButtonEnabled(false);
|
|
||||||
setModal(true);
|
setModal(true);
|
||||||
|
|
||||||
connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
connect(mLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotUpdateOkButton(QString)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextInputDialog::exec()
|
int Launcher::TextInputDialog::exec()
|
||||||
{
|
{
|
||||||
mLineEdit->clear();
|
mLineEdit->clear();
|
||||||
mLineEdit->setFocus();
|
mLineEdit->setFocus();
|
||||||
return QDialog::exec();
|
return QDialog::exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextInputDialog::setOkButtonEnabled(bool enabled)
|
QString Launcher::TextInputDialog::getText() const
|
||||||
{
|
{
|
||||||
QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok);
|
return mLineEdit->text();
|
||||||
okButton->setEnabled(enabled);
|
}
|
||||||
|
|
||||||
QPalette *palette = new QPalette();
|
void Launcher::TextInputDialog::slotUpdateOkButton(QString text)
|
||||||
palette->setColor(QPalette::Text,Qt::red);
|
{
|
||||||
|
bool enabled = !(text.isEmpty());
|
||||||
|
mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(enabled);
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled)
|
||||||
mLineEdit->setPalette(QApplication::palette());
|
mLineEdit->setPalette(QApplication::palette());
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
// Existing profile name, make the text red
|
// Existing profile name, make the text red
|
||||||
|
QPalette *palette = new QPalette();
|
||||||
|
palette->setColor(QPalette::Text,Qt::red);
|
||||||
mLineEdit->setPalette(*palette);
|
mLineEdit->setPalette(*palette);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Launcher::TextInputDialog::DialogLineEdit::DialogLineEdit (QWidget *parent) :
|
||||||
|
LineEdit (parent)
|
||||||
|
{
|
||||||
|
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||||
|
|
||||||
|
setObjectName(QString("LineEdit"));
|
||||||
|
setStyleSheet(QString("LineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1));
|
||||||
|
QSize msz = minimumSizeHint();
|
||||||
|
setMinimumSize(qMax(msz.width(), mClearButton->sizeHint().height() + frameWidth * 2 + 2),
|
||||||
|
qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,27 +2,39 @@
|
||||||
#define TEXTINPUTDIALOG_HPP
|
#define TEXTINPUTDIALOG_HPP
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
//#include "lineedit.hpp"
|
|
||||||
|
#include "lineedit.hpp"
|
||||||
|
|
||||||
class QDialogButtonBox;
|
class QDialogButtonBox;
|
||||||
class LineEdit;
|
|
||||||
|
|
||||||
class TextInputDialog : public QDialog
|
namespace Launcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class TextInputDialog : public QDialog
|
||||||
public:
|
{
|
||||||
explicit TextInputDialog(const QString& title, const QString &text, QWidget *parent = 0);
|
Q_OBJECT
|
||||||
inline LineEdit *lineEdit() { return mLineEdit; }
|
|
||||||
void setOkButtonEnabled(bool enabled);
|
|
||||||
|
|
||||||
LineEdit *mLineEdit;
|
class DialogLineEdit : public LineEdit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit DialogLineEdit (QWidget *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
int exec();
|
DialogLineEdit *mLineEdit;
|
||||||
|
QDialogButtonBox *mButtonBox;
|
||||||
|
|
||||||
private:
|
public:
|
||||||
QDialogButtonBox *mButtonBox;
|
|
||||||
|
|
||||||
|
explicit TextInputDialog(const QString& title, const QString &text, QWidget *parent = 0);
|
||||||
|
~TextInputDialog () {}
|
||||||
|
|
||||||
};
|
QString getText() const;
|
||||||
|
|
||||||
|
int exec();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void slotUpdateOkButton(QString text);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // TEXTINPUTDIALOG_HPP
|
#endif // TEXTINPUTDIALOG_HPP
|
||||||
|
|
|
@ -813,8 +813,7 @@ void MwIniImporter::importArchives(multistrmap &cfg, const multistrmap &ini) con
|
||||||
}
|
}
|
||||||
|
|
||||||
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) const {
|
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) const {
|
||||||
std::vector<std::string> esmFiles;
|
std::vector<std::string> contentFiles;
|
||||||
std::vector<std::string> espFiles;
|
|
||||||
std::string baseGameFile("Game Files:GameFile");
|
std::string baseGameFile("Game Files:GameFile");
|
||||||
std::string gameFile("");
|
std::string gameFile("");
|
||||||
|
|
||||||
|
@ -832,29 +831,19 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) co
|
||||||
std::string filetype(entry->substr(entry->length()-3));
|
std::string filetype(entry->substr(entry->length()-3));
|
||||||
Misc::StringUtils::toLower(filetype);
|
Misc::StringUtils::toLower(filetype);
|
||||||
|
|
||||||
if(filetype.compare("esm") == 0) {
|
if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) {
|
||||||
esmFiles.push_back(*entry);
|
contentFiles.push_back(*entry);
|
||||||
}
|
|
||||||
else if(filetype.compare("esp") == 0) {
|
|
||||||
espFiles.push_back(*entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gameFile = "";
|
gameFile = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.erase("master");
|
cfg.erase("content");
|
||||||
cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("master", std::vector<std::string>() ) );
|
cfg.insert( std::make_pair("content", std::vector<std::string>() ) );
|
||||||
|
|
||||||
for(std::vector<std::string>::const_iterator it=esmFiles.begin(); it!=esmFiles.end(); ++it) {
|
for(std::vector<std::string>::const_iterator it=contentFiles.begin(); it!=contentFiles.end(); ++it) {
|
||||||
cfg["master"].push_back(*it);
|
cfg["content"].push_back(*it);
|
||||||
}
|
|
||||||
|
|
||||||
cfg.erase("plugin");
|
|
||||||
cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("plugin", std::vector<std::string>() ) );
|
|
||||||
|
|
||||||
for(std::vector<std::string>::const_iterator it=espFiles.begin(); it!=espFiles.end(); ++it) {
|
|
||||||
cfg["plugin"].push_back(*it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ opencs_units (. editor)
|
||||||
set (CMAKE_BUILD_TYPE DEBUG)
|
set (CMAKE_BUILD_TYPE DEBUG)
|
||||||
|
|
||||||
opencs_units (model/doc
|
opencs_units (model/doc
|
||||||
document
|
document operation saving
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (model/doc
|
opencs_units_noqt (model/doc
|
||||||
documentmanager
|
documentmanager stage savingstate savingstages
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_hdrs_noqt (model/doc
|
opencs_hdrs_noqt (model/doc
|
||||||
|
@ -33,18 +33,18 @@ opencs_hdrs_noqt (model/world
|
||||||
|
|
||||||
|
|
||||||
opencs_units (model/tools
|
opencs_units (model/tools
|
||||||
tools operation reportmodel
|
tools reportmodel
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (model/tools
|
opencs_units_noqt (model/tools
|
||||||
stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||||
birthsigncheck spellcheck
|
birthsigncheck spellcheck
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
opencs_units (view/doc
|
opencs_units (view/doc
|
||||||
viewmanager view operations operation subview startup filedialog newgame filewidget
|
viewmanager view operations operation subview startup filedialog newgame
|
||||||
adjusterwidget
|
filewidget adjusterwidget
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ opencs_units (view/world
|
||||||
opencs_units_noqt (view/world
|
opencs_units_noqt (view/world
|
||||||
dialoguesubview subviews
|
dialoguesubview subviews
|
||||||
enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
||||||
scripthighlighter idvalidator
|
scripthighlighter idvalidator dialoguecreator
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,11 +124,13 @@ opencs_units (view/filter
|
||||||
set (OPENCS_US
|
set (OPENCS_US
|
||||||
)
|
)
|
||||||
|
|
||||||
set (OPENCS_RES ../../files/opencs/resources.qrc
|
set (OPENCS_RES ${CMAKE_SOURCE_DIR}/files/opencs/resources.qrc
|
||||||
../../files/launcher/launcher.qrc
|
${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc
|
||||||
)
|
)
|
||||||
|
|
||||||
set (OPENCS_UI ../../files/ui/datafilespage.ui
|
set (OPENCS_UI
|
||||||
|
${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
||||||
|
${CMAKE_SOURCE_DIR}/files/ui/filedialog.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR})
|
source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR})
|
||||||
|
|
|
@ -8,15 +8,17 @@
|
||||||
|
|
||||||
#include "model/doc/document.hpp"
|
#include "model/doc/document.hpp"
|
||||||
#include "model/world/data.hpp"
|
#include "model/world/data.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
CS::Editor::Editor()
|
||||||
CS::Editor::Editor() : mViewManager (mDocumentManager)
|
: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager)
|
||||||
{
|
{
|
||||||
mIpcServerName = "org.openmw.OpenCS";
|
mIpcServerName = "org.openmw.OpenCS";
|
||||||
|
|
||||||
setupDataFiles();
|
setupDataFiles();
|
||||||
|
|
||||||
mNewGame.setLocalData (mLocal);
|
mNewGame.setLocalData (mLocal);
|
||||||
|
mFileDialog.setLocalData (mLocal);
|
||||||
|
|
||||||
connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ()));
|
connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ()));
|
||||||
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
||||||
|
@ -28,23 +30,27 @@ CS::Editor::Editor() : mViewManager (mDocumentManager)
|
||||||
connect (&mStartup, SIGNAL (loadDocument()), this, SLOT (loadDocument ()));
|
connect (&mStartup, SIGNAL (loadDocument()), this, SLOT (loadDocument ()));
|
||||||
connect (&mStartup, SIGNAL (editConfig()), this, SLOT (showSettings ()));
|
connect (&mStartup, SIGNAL (editConfig()), this, SLOT (showSettings ()));
|
||||||
|
|
||||||
connect (&mFileDialog, SIGNAL(openFiles()), this, SLOT(openFiles()));
|
connect (&mFileDialog, SIGNAL(signalOpenFiles (const boost::filesystem::path&)),
|
||||||
connect (&mFileDialog, SIGNAL(createNewFile()), this, SLOT(createNewFile()));
|
this, SLOT(openFiles (const boost::filesystem::path&)));
|
||||||
|
|
||||||
|
connect (&mFileDialog, SIGNAL(signalCreateNewFile (const boost::filesystem::path&)),
|
||||||
|
this, SLOT(createNewFile (const boost::filesystem::path&)));
|
||||||
|
|
||||||
connect (&mNewGame, SIGNAL (createRequest (const boost::filesystem::path&)),
|
connect (&mNewGame, SIGNAL (createRequest (const boost::filesystem::path&)),
|
||||||
this, SLOT (createNewGame (const boost::filesystem::path&)));
|
this, SLOT (createNewGame (const boost::filesystem::path&)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::setupDataFiles()
|
void CS::Editor::setupDataFiles()
|
||||||
{
|
{
|
||||||
boost::program_options::variables_map variables;
|
boost::program_options::variables_map variables;
|
||||||
boost::program_options::options_description desc;
|
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
|
||||||
|
|
||||||
desc.add_options()
|
desc.add_options()
|
||||||
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
|
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
|
||||||
("data-local", boost::program_options::value<std::string>()->default_value(""))
|
("data-local", boost::program_options::value<std::string>()->default_value(""))
|
||||||
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
|
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
|
||||||
("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
|
("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
|
||||||
|
("resources", boost::program_options::value<std::string>()->default_value("resources"));
|
||||||
|
|
||||||
boost::program_options::notify(variables);
|
boost::program_options::notify(variables);
|
||||||
|
|
||||||
|
@ -79,13 +85,16 @@ void CS::Editor::setupDataFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the charset for reading the esm/esp files
|
// Set the charset for reading the esm/esp files
|
||||||
QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
|
// QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
|
||||||
mFileDialog.setEncoding(encoding);
|
//mFileDialog.setEncoding(encoding);
|
||||||
|
|
||||||
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
||||||
|
|
||||||
|
mDocumentManager.setResourceDir (variables["resources"].as<std::string>());
|
||||||
|
|
||||||
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
|
||||||
QString path = QString::fromStdString(iter->string());
|
QString path = QString::fromStdString(iter->string());
|
||||||
mFileDialog.addFiles(path);
|
mFileDialog.addFiles(path);
|
||||||
}
|
}
|
||||||
|
@ -109,48 +118,39 @@ void CS::Editor::createGame()
|
||||||
void CS::Editor::createAddon()
|
void CS::Editor::createAddon()
|
||||||
{
|
{
|
||||||
mStartup.hide();
|
mStartup.hide();
|
||||||
|
mFileDialog.showDialog (CSVDoc::ContentAction_New);
|
||||||
mFileDialog.newFile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::loadDocument()
|
void CS::Editor::loadDocument()
|
||||||
{
|
{
|
||||||
mStartup.hide();
|
mStartup.hide();
|
||||||
|
mFileDialog.showDialog (CSVDoc::ContentAction_Edit);
|
||||||
mFileDialog.openFile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::openFiles()
|
void CS::Editor::openFiles (const boost::filesystem::path &savePath)
|
||||||
{
|
{
|
||||||
std::vector<boost::filesystem::path> files;
|
std::vector<boost::filesystem::path> files;
|
||||||
QStringList paths = mFileDialog.checkedItemsPaths();
|
|
||||||
|
|
||||||
foreach (const QString &path, paths) {
|
foreach (const QString &path, mFileDialog.selectedFilePaths())
|
||||||
files.push_back(path.toStdString());
|
files.push_back(path.toStdString());
|
||||||
}
|
|
||||||
|
|
||||||
/// \todo Get the save path from the file dialogue
|
CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, false);
|
||||||
|
|
||||||
CSMDoc::Document *document = mDocumentManager.addDocument (files, *files.rbegin(), false);
|
|
||||||
|
|
||||||
mViewManager.addView (document);
|
mViewManager.addView (document);
|
||||||
mFileDialog.hide();
|
mFileDialog.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::createNewFile()
|
void CS::Editor::createNewFile (const boost::filesystem::path &savePath)
|
||||||
{
|
{
|
||||||
std::vector<boost::filesystem::path> files;
|
std::vector<boost::filesystem::path> files;
|
||||||
QStringList paths = mFileDialog.checkedItemsPaths();
|
|
||||||
|
|
||||||
foreach (const QString &path, paths) {
|
foreach (const QString &path, mFileDialog.selectedFilePaths()) {
|
||||||
files.push_back(path.toStdString());
|
files.push_back(path.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
files.push_back(mFileDialog.fileName().toStdString());
|
files.push_back(mFileDialog.filename().toStdString());
|
||||||
|
|
||||||
/// \todo Get the save path from the file dialogue.
|
CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, true);
|
||||||
|
|
||||||
CSMDoc::Document *document = mDocumentManager.addDocument (files, *files.rbegin(), true);
|
|
||||||
|
|
||||||
mViewManager.addView (document);
|
mViewManager.addView (document);
|
||||||
mFileDialog.hide();
|
mFileDialog.hide();
|
||||||
|
|
|
@ -26,15 +26,15 @@ namespace CS
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
Files::ConfigurationManager mCfgMgr;
|
||||||
CSMSettings::UserSettings mUserSettings;
|
CSMSettings::UserSettings mUserSettings;
|
||||||
CSMDoc::DocumentManager mDocumentManager;
|
CSMDoc::DocumentManager mDocumentManager;
|
||||||
CSVDoc::ViewManager mViewManager;
|
CSVDoc::ViewManager mViewManager;
|
||||||
CSVDoc::StartupDialogue mStartup;
|
CSVDoc::StartupDialogue mStartup;
|
||||||
CSVDoc::NewGameDialogue mNewGame;
|
CSVDoc::NewGameDialogue mNewGame;
|
||||||
CSVSettings::UserSettingsDialog mSettings;
|
CSVSettings::UserSettingsDialog mSettings;
|
||||||
FileDialog mFileDialog;
|
CSVDoc::FileDialog mFileDialog;
|
||||||
|
|
||||||
Files::ConfigurationManager mCfgMgr;
|
|
||||||
boost::filesystem::path mLocal;
|
boost::filesystem::path mLocal;
|
||||||
|
|
||||||
void setupDataFiles();
|
void setupDataFiles();
|
||||||
|
@ -59,8 +59,8 @@ namespace CS
|
||||||
void createAddon();
|
void createAddon();
|
||||||
|
|
||||||
void loadDocument();
|
void loadDocument();
|
||||||
void openFiles();
|
void openFiles (const boost::filesystem::path &path);
|
||||||
void createNewFile();
|
void createNewFile (const boost::filesystem::path& path);
|
||||||
void createNewGame (const boost::filesystem::path& file);
|
void createNewGame (const boost::filesystem::path& file);
|
||||||
|
|
||||||
void showStartup();
|
void showStartup();
|
||||||
|
|
|
@ -42,7 +42,7 @@ int main(int argc, char *argv[])
|
||||||
if(!editor.makeIPCServer())
|
if(!editor.makeIPCServer())
|
||||||
{
|
{
|
||||||
editor.connectToIPCServer();
|
editor.connectToIPCServer();
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return editor.run();
|
return editor.run();
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#ifndef Q_MOC_RUN
|
||||||
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
assert (begin!=end);
|
assert (begin!=end);
|
||||||
|
|
||||||
|
@ -12,10 +19,10 @@ void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_i
|
||||||
--end2;
|
--end2;
|
||||||
|
|
||||||
for (std::vector<boost::filesystem::path>::const_iterator iter (begin); iter!=end2; ++iter)
|
for (std::vector<boost::filesystem::path>::const_iterator iter (begin); iter!=end2; ++iter)
|
||||||
getData().loadFile (*iter, true);
|
getData().loadFile (*iter, true, false);
|
||||||
|
|
||||||
if (lastAsModified)
|
if (lastAsModified)
|
||||||
getData().loadFile (*end2, false);
|
getData().loadFile (*end2, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::addGmsts()
|
void CSMDoc::Document::addGmsts()
|
||||||
|
@ -2058,9 +2065,9 @@ void CSMDoc::Document::addOptionalGlobals()
|
||||||
{
|
{
|
||||||
static const char *sGlobals[] =
|
static const char *sGlobals[] =
|
||||||
{
|
{
|
||||||
"dayspassed",
|
"DaysPassed",
|
||||||
"pcwerewolf",
|
"PCWerewolf",
|
||||||
"pcyear",
|
"PCYear",
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2137,11 +2144,86 @@ void CSMDoc::Document::createBase()
|
||||||
|
|
||||||
getData().getSkills().add (record);
|
getData().getSkills().add (record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *sVoice[] =
|
||||||
|
{
|
||||||
|
"Intruder",
|
||||||
|
"Attack",
|
||||||
|
"Hello",
|
||||||
|
"Thief",
|
||||||
|
"Alarm",
|
||||||
|
"Idle",
|
||||||
|
"Flee",
|
||||||
|
"Hit",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0; sVoice[i]; ++i)
|
||||||
|
{
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = sVoice[i];
|
||||||
|
record.mType = ESM::Dialogue::Voice;
|
||||||
|
record.blank();
|
||||||
|
|
||||||
|
getData().getTopics().add (record);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *sGreetings[] =
|
||||||
|
{
|
||||||
|
"Greeting 0",
|
||||||
|
"Greeting 1",
|
||||||
|
"Greeting 2",
|
||||||
|
"Greeting 3",
|
||||||
|
"Greeting 4",
|
||||||
|
"Greeting 5",
|
||||||
|
"Greeting 6",
|
||||||
|
"Greeting 7",
|
||||||
|
"Greeting 8",
|
||||||
|
"Greeting 9",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0; sGreetings[i]; ++i)
|
||||||
|
{
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = sGreetings[i];
|
||||||
|
record.mType = ESM::Dialogue::Greeting;
|
||||||
|
record.blank();
|
||||||
|
|
||||||
|
getData().getTopics().add (record);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *sPersuasion[] =
|
||||||
|
{
|
||||||
|
"Intimidate Success",
|
||||||
|
"Intimidate Fail",
|
||||||
|
"Service Refusal",
|
||||||
|
"Admire Success",
|
||||||
|
"Taunt Success",
|
||||||
|
"Bribe Success",
|
||||||
|
"Info Refusal",
|
||||||
|
"Admire Fail",
|
||||||
|
"Taunt Fail",
|
||||||
|
"Bribe Fail",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0; sPersuasion[i]; ++i)
|
||||||
|
{
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = sPersuasion[i];
|
||||||
|
record.mType = ESM::Dialogue::Persuasion;
|
||||||
|
record.blank();
|
||||||
|
|
||||||
|
getData().getTopics().add (record);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files,
|
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_)
|
||||||
const boost::filesystem::path& savePath, bool new_)
|
: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir),
|
||||||
: mSavePath (savePath), mTools (mData)
|
mProjectPath ((configuration.getUserPath() / "projects") /
|
||||||
|
(savePath.filename().string() + ".project")),
|
||||||
|
mSaving (*this, mProjectPath)
|
||||||
{
|
{
|
||||||
if (files.empty())
|
if (files.empty())
|
||||||
throw std::runtime_error ("Empty content file sequence");
|
throw std::runtime_error ("Empty content file sequence");
|
||||||
|
@ -2158,6 +2240,34 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files,
|
||||||
load (files.begin(), end, !new_);
|
load (files.begin(), end, !new_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_)
|
||||||
|
{
|
||||||
|
mData.setDescription ("");
|
||||||
|
mData.setAuthor ("");
|
||||||
|
}
|
||||||
|
/// \todo un-outcomment the else, once loading an existing content file works properly again.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (boost::filesystem::exists (mProjectPath))
|
||||||
|
{
|
||||||
|
getData().loadFile (mProjectPath, false, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boost::filesystem::path locCustomFiltersPath (configuration.getUserPath());
|
||||||
|
locCustomFiltersPath /= "defaultfilters";
|
||||||
|
if (boost::filesystem::exists(locCustomFiltersPath))
|
||||||
|
{
|
||||||
|
boost::filesystem::copy_file (locCustomFiltersPath, mProjectPath);
|
||||||
|
} else {
|
||||||
|
boost::filesystem::path filters(mResDir);
|
||||||
|
filters /= "defaultfilters";
|
||||||
|
boost::filesystem::copy_file(filters, mProjectPath);
|
||||||
|
}
|
||||||
|
getData().loadFile (mProjectPath, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addOptionalGmsts();
|
addOptionalGmsts();
|
||||||
addOptionalGlobals();
|
addOptionalGlobals();
|
||||||
|
|
||||||
|
@ -2166,9 +2276,10 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files,
|
||||||
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
||||||
|
|
||||||
// dummy implementation -> remove when proper save is implemented.
|
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
mSaveCount = 0;
|
connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
||||||
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
|
connect (&mSaving, SIGNAL (reportMessage (const QString&, int)),
|
||||||
|
this, SLOT (reportMessage (const QString&, int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::~Document()
|
CSMDoc::Document::~Document()
|
||||||
|
@ -2187,7 +2298,7 @@ int CSMDoc::Document::getState() const
|
||||||
if (!mUndoStack.isClean())
|
if (!mUndoStack.isClean())
|
||||||
state |= State_Modified;
|
state |= State_Modified;
|
||||||
|
|
||||||
if (mSaveCount)
|
if (mSaving.isRunning())
|
||||||
state |= State_Locked | State_Saving | State_Operation;
|
state |= State_Locked | State_Saving | State_Operation;
|
||||||
|
|
||||||
if (int operations = mTools.getRunningOperations())
|
if (int operations = mTools.getRunningOperations())
|
||||||
|
@ -2201,12 +2312,20 @@ const boost::filesystem::path& CSMDoc::Document::getSavePath() const
|
||||||
return mSavePath;
|
return mSavePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<boost::filesystem::path>& CSMDoc::Document::getContentFiles() const
|
||||||
|
{
|
||||||
|
return mContentFiles;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::save()
|
void CSMDoc::Document::save()
|
||||||
{
|
{
|
||||||
mSaveCount = 1;
|
if (mSaving.isRunning())
|
||||||
mSaveTimer.start (500);
|
throw std::logic_error (
|
||||||
|
"Failed to initiate save, because a save operation is already running.");
|
||||||
|
|
||||||
|
mSaving.start();
|
||||||
|
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
emit progress (1, 16, State_Saving, 1, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSMDoc::Document::verify()
|
CSMWorld::UniversalId CSMDoc::Document::verify()
|
||||||
|
@ -2218,46 +2337,28 @@ CSMWorld::UniversalId CSMDoc::Document::verify()
|
||||||
|
|
||||||
void CSMDoc::Document::abortOperation (int type)
|
void CSMDoc::Document::abortOperation (int type)
|
||||||
{
|
{
|
||||||
mTools.abortOperation (type);
|
|
||||||
|
|
||||||
if (type==State_Saving)
|
if (type==State_Saving)
|
||||||
{
|
mSaving.abort();
|
||||||
mSaveCount=0;
|
else
|
||||||
mSaveTimer.stop();
|
mTools.abortOperation (type);
|
||||||
emit stateChanged (getState(), this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSMDoc::Document::modificationStateChanged (bool clean)
|
void CSMDoc::Document::modificationStateChanged (bool clean)
|
||||||
{
|
{
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Document::reportMessage (const QString& message, int type)
|
||||||
|
{
|
||||||
|
/// \todo find a better way to get these messages to the user.
|
||||||
|
std::cout << message.toUtf8().constData() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::operationDone (int type)
|
void CSMDoc::Document::operationDone (int type)
|
||||||
{
|
{
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::saving()
|
|
||||||
{
|
|
||||||
++mSaveCount;
|
|
||||||
|
|
||||||
emit progress (mSaveCount, 16, State_Saving, 1, this);
|
|
||||||
|
|
||||||
if (mSaveCount>15)
|
|
||||||
{
|
|
||||||
//clear the stack before resetting the save state
|
|
||||||
//to avoid emitting incorrect states
|
|
||||||
mUndoStack.setClean();
|
|
||||||
|
|
||||||
mSaveCount = 0;
|
|
||||||
mSaveTimer.stop();
|
|
||||||
emit stateChanged (getState(), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const CSMWorld::Data& CSMDoc::Document::getData() const
|
const CSMWorld::Data& CSMDoc::Document::getData() const
|
||||||
{
|
{
|
||||||
return mData;
|
return mData;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../tools/tools.hpp"
|
#include "../tools/tools.hpp"
|
||||||
|
|
||||||
#include "state.hpp"
|
#include "state.hpp"
|
||||||
|
#include "saving.hpp"
|
||||||
|
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
@ -23,6 +24,11 @@ namespace ESM
|
||||||
struct Global;
|
struct Global;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
class ConfigurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Document : public QObject
|
class Document : public QObject
|
||||||
|
@ -32,16 +38,17 @@ namespace CSMDoc
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::filesystem::path mSavePath;
|
boost::filesystem::path mSavePath;
|
||||||
|
std::vector<boost::filesystem::path> mContentFiles;
|
||||||
CSMWorld::Data mData;
|
CSMWorld::Data mData;
|
||||||
CSMTools::Tools mTools;
|
CSMTools::Tools mTools;
|
||||||
|
boost::filesystem::path mProjectPath;
|
||||||
|
Saving mSaving;
|
||||||
|
boost::filesystem::path mResDir;
|
||||||
|
|
||||||
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
|
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
|
||||||
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
|
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
|
||||||
QUndoStack mUndoStack;
|
QUndoStack mUndoStack;
|
||||||
|
|
||||||
int mSaveCount; ///< dummy implementation -> remove when proper save is implemented.
|
|
||||||
QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented.
|
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Document (const Document&);
|
Document (const Document&);
|
||||||
Document& operator= (const Document&);
|
Document& operator= (const Document&);
|
||||||
|
@ -64,8 +71,7 @@ namespace CSMDoc
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Document (const std::vector<boost::filesystem::path>& files,
|
Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_);
|
||||||
const boost::filesystem::path& savePath, bool new_);
|
|
||||||
|
|
||||||
~Document();
|
~Document();
|
||||||
|
|
||||||
|
@ -75,6 +81,10 @@ namespace CSMDoc
|
||||||
|
|
||||||
const boost::filesystem::path& getSavePath() const;
|
const boost::filesystem::path& getSavePath() const;
|
||||||
|
|
||||||
|
const std::vector<boost::filesystem::path>& getContentFiles() const;
|
||||||
|
///< \attention The last element in this collection is the file that is being edited,
|
||||||
|
/// but with its original path instead of the save path.
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
CSMWorld::UniversalId verify();
|
CSMWorld::UniversalId verify();
|
||||||
|
@ -98,10 +108,9 @@ namespace CSMDoc
|
||||||
|
|
||||||
void modificationStateChanged (bool clean);
|
void modificationStateChanged (bool clean);
|
||||||
|
|
||||||
void operationDone (int type);
|
void reportMessage (const QString& message, int type);
|
||||||
|
|
||||||
void saving();
|
void operationDone (int type);
|
||||||
///< dummy implementation -> remove when proper save is implemented.
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -110,3 +119,4 @@ namespace CSMDoc
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,22 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#ifndef Q_MOC_RUN
|
||||||
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::DocumentManager::DocumentManager() {}
|
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
|
||||||
|
: mConfiguration (configuration)
|
||||||
|
{
|
||||||
|
boost::filesystem::path projectPath = configuration.getUserPath() / "projects";
|
||||||
|
|
||||||
|
if (!boost::filesystem::is_directory (projectPath))
|
||||||
|
boost::filesystem::create_directories (projectPath);
|
||||||
|
}
|
||||||
|
|
||||||
CSMDoc::DocumentManager::~DocumentManager()
|
CSMDoc::DocumentManager::~DocumentManager()
|
||||||
{
|
{
|
||||||
|
@ -17,7 +30,7 @@ CSMDoc::DocumentManager::~DocumentManager()
|
||||||
CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||||
bool new_)
|
bool new_)
|
||||||
{
|
{
|
||||||
Document *document = new Document (files, savePath, new_);
|
Document *document = new Document (mConfiguration, files, savePath, mResDir, new_);
|
||||||
|
|
||||||
mDocuments.push_back (document);
|
mDocuments.push_back (document);
|
||||||
|
|
||||||
|
@ -36,3 +49,8 @@ bool CSMDoc::DocumentManager::removeDocument (Document *document)
|
||||||
|
|
||||||
return mDocuments.empty();
|
return mDocuments.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& parResDir)
|
||||||
|
{
|
||||||
|
mResDir = boost::filesystem::system_complete(parResDir);
|
||||||
|
}
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
class ConfigurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Document;
|
class Document;
|
||||||
|
@ -13,18 +18,18 @@ namespace CSMDoc
|
||||||
class DocumentManager
|
class DocumentManager
|
||||||
{
|
{
|
||||||
std::vector<Document *> mDocuments;
|
std::vector<Document *> mDocuments;
|
||||||
|
const Files::ConfigurationManager& mConfiguration;
|
||||||
|
|
||||||
DocumentManager (const DocumentManager&);
|
DocumentManager (const DocumentManager&);
|
||||||
DocumentManager& operator= (const DocumentManager&);
|
DocumentManager& operator= (const DocumentManager&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DocumentManager();
|
DocumentManager (const Files::ConfigurationManager& configuration);
|
||||||
|
|
||||||
~DocumentManager();
|
~DocumentManager();
|
||||||
|
|
||||||
Document *addDocument (const std::vector<boost::filesystem::path>& files,
|
Document *addDocument (const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, bool new_);
|
||||||
const boost::filesystem::path& savePath, bool new_);
|
|
||||||
///< The ownership of the returned document is not transferred to the caller.
|
///< The ownership of the returned document is not transferred to the caller.
|
||||||
///
|
///
|
||||||
/// \param new_ Do not load the last content file in \a files and instead create in an
|
/// \param new_ Do not load the last content file in \a files and instead create in an
|
||||||
|
@ -32,6 +37,10 @@ namespace CSMDoc
|
||||||
|
|
||||||
bool removeDocument (Document *document);
|
bool removeDocument (Document *document);
|
||||||
///< \return last document removed?
|
///< \return last document removed?
|
||||||
|
void setResourceDir (const boost::filesystem::path& parResDir);
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::filesystem::path mResDir;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "../doc/state.hpp"
|
#include "state.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "stage.hpp"
|
||||||
|
|
||||||
void CSMTools::Operation::prepareStages()
|
void CSMDoc::Operation::prepareStages()
|
||||||
{
|
{
|
||||||
mCurrentStage = mStages.begin();
|
mCurrentStage = mStages.begin();
|
||||||
mCurrentStep = 0;
|
mCurrentStep = 0;
|
||||||
mCurrentStepTotal = 0;
|
mCurrentStepTotal = 0;
|
||||||
mTotalSteps = 0;
|
mTotalSteps = 0;
|
||||||
|
mError = false;
|
||||||
|
|
||||||
for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
|
for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
@ -24,38 +24,61 @@ void CSMTools::Operation::prepareStages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::Operation::Operation (int type) : mType (type) {}
|
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
|
||||||
|
: mType (type), mOrdered (ordered), mFinalAlways (finalAlways)
|
||||||
|
{
|
||||||
|
connect (this, SIGNAL (finished()), this, SLOT (operationDone()));
|
||||||
|
}
|
||||||
|
|
||||||
CSMTools::Operation::~Operation()
|
CSMDoc::Operation::~Operation()
|
||||||
{
|
{
|
||||||
for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
|
for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
|
||||||
delete iter->first;
|
delete iter->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Operation::run()
|
void CSMDoc::Operation::run()
|
||||||
{
|
{
|
||||||
prepareStages();
|
prepareStages();
|
||||||
|
|
||||||
QTimer timer;
|
QTimer timer;
|
||||||
|
|
||||||
timer.connect (&timer, SIGNAL (timeout()), this, SLOT (verify()));
|
timer.connect (&timer, SIGNAL (timeout()), this, SLOT (executeStage()));
|
||||||
|
|
||||||
timer.start (0);
|
timer.start (0);
|
||||||
|
|
||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Operation::appendStage (Stage *stage)
|
void CSMDoc::Operation::appendStage (Stage *stage)
|
||||||
{
|
{
|
||||||
mStages.push_back (std::make_pair (stage, 0));
|
mStages.push_back (std::make_pair (stage, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Operation::abort()
|
bool CSMDoc::Operation::hasError() const
|
||||||
{
|
{
|
||||||
exit();
|
return mError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Operation::verify()
|
void CSMDoc::Operation::abort()
|
||||||
|
{
|
||||||
|
if (!isRunning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mError = true;
|
||||||
|
|
||||||
|
if (mFinalAlways)
|
||||||
|
{
|
||||||
|
if (mStages.begin()!=mStages.end() && mCurrentStage!=--mStages.end())
|
||||||
|
{
|
||||||
|
mCurrentStep = 0;
|
||||||
|
mCurrentStage = --mStages.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mCurrentStage = mStages.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Operation::executeStage()
|
||||||
{
|
{
|
||||||
std::vector<std::string> messages;
|
std::vector<std::string> messages;
|
||||||
|
|
||||||
|
@ -68,7 +91,16 @@ void CSMTools::Operation::verify()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mCurrentStage->first->perform (mCurrentStep++, messages);
|
try
|
||||||
|
{
|
||||||
|
mCurrentStage->first->perform (mCurrentStep++, messages);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
emit reportMessage (e.what(), mType);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
++mCurrentStepTotal;
|
++mCurrentStepTotal;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -82,3 +114,8 @@ void CSMTools::Operation::verify()
|
||||||
if (mCurrentStage==mStages.end())
|
if (mCurrentStage==mStages.end())
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Operation::operationDone()
|
||||||
|
{
|
||||||
|
emit done (mType);
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
#ifndef CSM_TOOLS_OPERATION_H
|
#ifndef CSM_DOC_OPERATION_H
|
||||||
#define CSM_TOOLS_OPERATION_H
|
#define CSM_DOC_OPERATION_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Stage;
|
class Stage;
|
||||||
|
|
||||||
|
@ -19,12 +19,17 @@ namespace CSMTools
|
||||||
int mCurrentStep;
|
int mCurrentStep;
|
||||||
int mCurrentStepTotal;
|
int mCurrentStepTotal;
|
||||||
int mTotalSteps;
|
int mTotalSteps;
|
||||||
|
int mOrdered;
|
||||||
|
bool mFinalAlways;
|
||||||
|
bool mError;
|
||||||
|
|
||||||
void prepareStages();
|
void prepareStages();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Operation (int type);
|
Operation (int type, bool ordered, bool finalAlways = false);
|
||||||
|
///< \param ordered Stages must be executed in the given order.
|
||||||
|
/// \param finalAlways Execute last stage even if an error occurred during earlier stages.
|
||||||
|
|
||||||
virtual ~Operation();
|
virtual ~Operation();
|
||||||
|
|
||||||
|
@ -35,19 +40,25 @@ namespace CSMTools
|
||||||
///
|
///
|
||||||
/// \attention Do no call this function while this Operation is running.
|
/// \attention Do no call this function while this Operation is running.
|
||||||
|
|
||||||
|
bool hasError() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void progress (int current, int max, int type);
|
void progress (int current, int max, int type);
|
||||||
|
|
||||||
void reportMessage (const QString& message, int type);
|
void reportMessage (const QString& message, int type);
|
||||||
|
|
||||||
|
void done (int type);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void abort();
|
void abort();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void verify();
|
void executeStage();
|
||||||
|
|
||||||
|
void operationDone();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
74
apps/opencs/model/doc/saving.cpp
Normal file
74
apps/opencs/model/doc/saving.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
#include "saving.hpp"
|
||||||
|
|
||||||
|
#include "../world/data.hpp"
|
||||||
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
|
#include "state.hpp"
|
||||||
|
#include "savingstages.hpp"
|
||||||
|
#include "document.hpp"
|
||||||
|
|
||||||
|
CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath)
|
||||||
|
: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath)
|
||||||
|
{
|
||||||
|
// save project file
|
||||||
|
appendStage (new OpenSaveStage (mDocument, mState, true));
|
||||||
|
|
||||||
|
appendStage (new WriteHeaderStage (mDocument, mState, true));
|
||||||
|
|
||||||
|
appendStage (new WriteFilterStage (mDocument, mState, CSMFilter::Filter::Scope_Project));
|
||||||
|
|
||||||
|
appendStage (new CloseSaveStage (mState));
|
||||||
|
|
||||||
|
// save content file
|
||||||
|
appendStage (new OpenSaveStage (mDocument, mState, false));
|
||||||
|
|
||||||
|
appendStage (new WriteHeaderStage (mDocument, mState, false));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Global> >
|
||||||
|
(mDocument.getData().getGlobals(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::GameSetting> >
|
||||||
|
(mDocument.getData().getGmsts(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Skill> >
|
||||||
|
(mDocument.getData().getSkills(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Class> >
|
||||||
|
(mDocument.getData().getClasses(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Faction> >
|
||||||
|
(mDocument.getData().getFactions(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Race> >
|
||||||
|
(mDocument.getData().getRaces(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Sound> >
|
||||||
|
(mDocument.getData().getSounds(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script> >
|
||||||
|
(mDocument.getData().getScripts(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Region> >
|
||||||
|
(mDocument.getData().getRegions(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::BirthSign> >
|
||||||
|
(mDocument.getData().getBirthsigns(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Spell> >
|
||||||
|
(mDocument.getData().getSpells(), mState));
|
||||||
|
|
||||||
|
/// \todo deal with info records for topcis and journals
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Dialogue> >
|
||||||
|
(mDocument.getData().getTopics(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Dialogue> >
|
||||||
|
(mDocument.getData().getJournals(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
|
|
||||||
|
appendStage (new CloseSaveStage (mState));
|
||||||
|
|
||||||
|
appendStage (new FinalSavingStage (mDocument, mState));
|
||||||
|
}
|
27
apps/opencs/model/doc/saving.hpp
Normal file
27
apps/opencs/model/doc/saving.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef CSM_DOC_SAVING_H
|
||||||
|
#define CSM_DOC_SAVING_H
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include "operation.hpp"
|
||||||
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
|
||||||
|
class Saving : public Operation
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Saving (Document& document, const boost::filesystem::path& projectPath);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
161
apps/opencs/model/doc/savingstages.cpp
Normal file
161
apps/opencs/model/doc/savingstages.cpp
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
|
||||||
|
#include "savingstages.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <QUndoStack>
|
||||||
|
|
||||||
|
#include "document.hpp"
|
||||||
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
|
CSMDoc::OpenSaveStage::OpenSaveStage (Document& document, SavingState& state, bool projectFile)
|
||||||
|
: mDocument (document), mState (state), mProjectFile (projectFile)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::OpenSaveStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::OpenSaveStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
mState.start (mDocument, mProjectFile);
|
||||||
|
|
||||||
|
mState.getStream().open ((mProjectFile ? mState.getPath() : mState.getTmpPath()).string().c_str());
|
||||||
|
|
||||||
|
if (!mState.getStream().is_open())
|
||||||
|
throw std::runtime_error ("failed to open stream for saving");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::WriteHeaderStage::WriteHeaderStage (Document& document, SavingState& state, bool simple)
|
||||||
|
: mDocument (document), mState (state), mSimple (simple)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::WriteHeaderStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::WriteHeaderStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
mState.getWriter().setVersion();
|
||||||
|
|
||||||
|
mState.getWriter().clearMaster();
|
||||||
|
|
||||||
|
mState.getWriter().setFormat (0);
|
||||||
|
|
||||||
|
if (mSimple)
|
||||||
|
{
|
||||||
|
mState.getWriter().setAuthor ("");
|
||||||
|
mState.getWriter().setDescription ("");
|
||||||
|
mState.getWriter().setRecordCount (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mState.getWriter().setAuthor (mDocument.getData().getAuthor());
|
||||||
|
mState.getWriter().setDescription (mDocument.getData().getDescription());
|
||||||
|
mState.getWriter().setRecordCount (
|
||||||
|
mDocument.getData().count (CSMWorld::RecordBase::State_Modified) +
|
||||||
|
mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) +
|
||||||
|
mDocument.getData().count (CSMWorld::RecordBase::State_Deleted));
|
||||||
|
|
||||||
|
/// \todo refine dependency list (at least remove redundant dependencies)
|
||||||
|
std::vector<boost::filesystem::path> dependencies = mDocument.getContentFiles();
|
||||||
|
std::vector<boost::filesystem::path>::const_iterator end (--dependencies.end());
|
||||||
|
|
||||||
|
for (std::vector<boost::filesystem::path>::const_iterator iter (dependencies.begin());
|
||||||
|
iter!=end; ++iter)
|
||||||
|
{
|
||||||
|
std::string name = iter->filename().string();
|
||||||
|
uint64_t size = boost::filesystem::file_size (*iter);
|
||||||
|
|
||||||
|
mState.getWriter().addMaster (name, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mState.getWriter().save (mState.getStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::WriteRefIdCollectionStage::WriteRefIdCollectionStage (Document& document, SavingState& state)
|
||||||
|
: mDocument (document), mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::WriteRefIdCollectionStage::setup()
|
||||||
|
{
|
||||||
|
return mDocument.getData().getReferenceables().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::WriteRefIdCollectionStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
mDocument.getData().getReferenceables().save (stage, mState.getWriter());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::WriteFilterStage::WriteFilterStage (Document& document, SavingState& state,
|
||||||
|
CSMFilter::Filter::Scope scope)
|
||||||
|
: WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> > (document.getData().getFilters(),
|
||||||
|
state),
|
||||||
|
mDocument (document), mScope (scope)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CSMDoc::WriteFilterStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMFilter::Filter>& record =
|
||||||
|
mDocument.getData().getFilters().getRecord (stage);
|
||||||
|
|
||||||
|
if (record.get().mScope==mScope)
|
||||||
|
WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >::perform (stage, messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state)
|
||||||
|
: mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::CloseSaveStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::CloseSaveStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
mState.getStream().close();
|
||||||
|
|
||||||
|
if (!mState.getStream())
|
||||||
|
throw std::runtime_error ("saving failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::FinalSavingStage::FinalSavingStage (Document& document, SavingState& state)
|
||||||
|
: mDocument (document), mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::FinalSavingStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::FinalSavingStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
if (mState.hasError())
|
||||||
|
{
|
||||||
|
mState.getWriter().close();
|
||||||
|
mState.getStream().close();
|
||||||
|
|
||||||
|
if (boost::filesystem::exists (mState.getTmpPath()))
|
||||||
|
boost::filesystem::remove (mState.getTmpPath());
|
||||||
|
}
|
||||||
|
else if (!mState.isProjectFile())
|
||||||
|
{
|
||||||
|
if (boost::filesystem::exists (mState.getPath()))
|
||||||
|
boost::filesystem::remove (mState.getPath());
|
||||||
|
|
||||||
|
boost::filesystem::rename (mState.getTmpPath(), mState.getPath());
|
||||||
|
|
||||||
|
mDocument.getUndoStack().setClean();
|
||||||
|
}
|
||||||
|
}
|
172
apps/opencs/model/doc/savingstages.hpp
Normal file
172
apps/opencs/model/doc/savingstages.hpp
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#ifndef CSM_DOC_SAVINGSTAGES_H
|
||||||
|
#define CSM_DOC_SAVINGSTAGES_H
|
||||||
|
|
||||||
|
#include "stage.hpp"
|
||||||
|
|
||||||
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
|
#include "../world/record.hpp"
|
||||||
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
|
#include "../filter/filter.hpp"
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
class SavingState;
|
||||||
|
|
||||||
|
class OpenSaveStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
bool mProjectFile;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
OpenSaveStage (Document& document, SavingState& state, bool projectFile);
|
||||||
|
///< \param projectFile Saving the project file instead of the content file.
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
class WriteHeaderStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
bool mSimple;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteHeaderStage (Document& document, SavingState& state, bool simple);
|
||||||
|
///< \param simple Simplified header (used for project files).
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class CollectionT>
|
||||||
|
class WriteCollectionStage : public Stage
|
||||||
|
{
|
||||||
|
const CollectionT& mCollection;
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteCollectionStage (const CollectionT& collection, SavingState& state);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class CollectionT>
|
||||||
|
WriteCollectionStage<CollectionT>::WriteCollectionStage (const CollectionT& collection,
|
||||||
|
SavingState& state)
|
||||||
|
: mCollection (collection), mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class CollectionT>
|
||||||
|
int WriteCollectionStage<CollectionT>::setup()
|
||||||
|
{
|
||||||
|
return mCollection.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class CollectionT>
|
||||||
|
void WriteCollectionStage<CollectionT>::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
|
||||||
|
|
||||||
|
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||||
|
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
std::string type;
|
||||||
|
for (int i=0; i<4; ++i)
|
||||||
|
/// \todo make endianess agnostic (change ESMWriter interface?)
|
||||||
|
type += reinterpret_cast<const char *> (&mCollection.getRecord (stage).mModified.sRecordId)[i];
|
||||||
|
|
||||||
|
mState.getWriter().startRecord (type);
|
||||||
|
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
|
||||||
|
mCollection.getRecord (stage).mModified.save (mState.getWriter());
|
||||||
|
mState.getWriter().endRecord (type);
|
||||||
|
}
|
||||||
|
else if (state==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
{
|
||||||
|
/// \todo write record with delete flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class WriteRefIdCollectionStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteRefIdCollectionStage (Document& document, SavingState& state);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WriteFilterStage : public WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
CSMFilter::Filter::Scope mScope;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope);
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CloseSaveStage : public Stage
|
||||||
|
{
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CloseSaveStage (SavingState& state);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
class FinalSavingStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FinalSavingStage (Document& document, SavingState& state);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
65
apps/opencs/model/doc/savingstate.cpp
Normal file
65
apps/opencs/model/doc/savingstate.cpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
|
#include "operation.hpp"
|
||||||
|
#include "document.hpp"
|
||||||
|
|
||||||
|
CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath)
|
||||||
|
: mOperation (operation),
|
||||||
|
/// \todo set encoding properly, once config implementation has been fixed.
|
||||||
|
mEncoder (ToUTF8::calculateEncoding ("win1252")),
|
||||||
|
mProjectPath (projectPath), mProjectFile (false)
|
||||||
|
{
|
||||||
|
mWriter.setEncoder (&mEncoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMDoc::SavingState::hasError() const
|
||||||
|
{
|
||||||
|
return mOperation.hasError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::SavingState::start (Document& document, bool project)
|
||||||
|
{
|
||||||
|
mProjectFile = project;
|
||||||
|
|
||||||
|
if (mStream.is_open())
|
||||||
|
mStream.close();
|
||||||
|
|
||||||
|
mStream.clear();
|
||||||
|
|
||||||
|
if (project)
|
||||||
|
mPath = mProjectPath;
|
||||||
|
else
|
||||||
|
mPath = document.getSavePath();
|
||||||
|
|
||||||
|
boost::filesystem::path file (mPath.filename().string() + ".tmp");
|
||||||
|
|
||||||
|
mTmpPath = mPath.parent_path();
|
||||||
|
|
||||||
|
mTmpPath /= file;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& CSMDoc::SavingState::getPath() const
|
||||||
|
{
|
||||||
|
return mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& CSMDoc::SavingState::getTmpPath() const
|
||||||
|
{
|
||||||
|
return mTmpPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream& CSMDoc::SavingState::getStream()
|
||||||
|
{
|
||||||
|
return mStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESM::ESMWriter& CSMDoc::SavingState::getWriter()
|
||||||
|
{
|
||||||
|
return mWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMDoc::SavingState::isProjectFile() const
|
||||||
|
{
|
||||||
|
return mProjectFile;
|
||||||
|
}
|
50
apps/opencs/model/doc/savingstate.hpp
Normal file
50
apps/opencs/model/doc/savingstate.hpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef CSM_DOC_SAVINGSTATE_H
|
||||||
|
#define CSM_DOC_SAVINGSTATE_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Operation;
|
||||||
|
class Document;
|
||||||
|
|
||||||
|
class SavingState
|
||||||
|
{
|
||||||
|
Operation& mOperation;
|
||||||
|
boost::filesystem::path mPath;
|
||||||
|
boost::filesystem::path mTmpPath;
|
||||||
|
ToUTF8::Utf8Encoder mEncoder;
|
||||||
|
std::ofstream mStream;
|
||||||
|
ESM::ESMWriter mWriter;
|
||||||
|
boost::filesystem::path mProjectPath;
|
||||||
|
bool mProjectFile;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SavingState (Operation& operation, const boost::filesystem::path& projectPath);
|
||||||
|
|
||||||
|
bool hasError() const;
|
||||||
|
|
||||||
|
void start (Document& document, bool project);
|
||||||
|
///< \param project Save project file instead of content file.
|
||||||
|
|
||||||
|
const boost::filesystem::path& getPath() const;
|
||||||
|
|
||||||
|
const boost::filesystem::path& getTmpPath() const;
|
||||||
|
|
||||||
|
std::ofstream& getStream();
|
||||||
|
|
||||||
|
ESM::ESMWriter& getWriter();
|
||||||
|
|
||||||
|
bool isProjectFile() const;
|
||||||
|
///< Currently saving project file? (instead of content file)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
4
apps/opencs/model/doc/stage.cpp
Normal file
4
apps/opencs/model/doc/stage.cpp
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
#include "stage.hpp"
|
||||||
|
|
||||||
|
CSMDoc::Stage::~Stage() {}
|
|
@ -1,10 +1,10 @@
|
||||||
#ifndef CSM_TOOLS_STAGE_H
|
#ifndef CSM_DOC_STAGE_H
|
||||||
#define CSM_TOOLS_STAGE_H
|
#define CSM_DOC_STAGE_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Stage
|
class Stage
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ namespace CSMTools
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages) = 0;
|
virtual void perform (int stage, std::vector<std::string>& messages) = 0;
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that birthsign records are internally consistent
|
/// \brief VerifyStage: make sure that birthsign records are internally consistent
|
||||||
class BirthsignCheckStage : public Stage
|
class BirthsignCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
|
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that class records are internally consistent
|
/// \brief VerifyStage: make sure that class records are internally consistent
|
||||||
class ClassCheckStage : public Stage
|
class ClassCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that faction records are internally consistent
|
/// \brief VerifyStage: make sure that faction records are internally consistent
|
||||||
class FactionCheckStage : public Stage
|
class FactionCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ namespace CSMWorld
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief Verify stage: make sure that records with specific IDs exist.
|
/// \brief Verify stage: make sure that records with specific IDs exist.
|
||||||
class MandatoryIdStage : public Stage
|
class MandatoryIdStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::CollectionBase& mIdCollection;
|
const CSMWorld::CollectionBase& mIdCollection;
|
||||||
CSMWorld::UniversalId mCollectionId;
|
CSMWorld::UniversalId mCollectionId;
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that race records are internally consistent
|
/// \brief VerifyStage: make sure that race records are internally consistent
|
||||||
class RaceCheckStage : public Stage
|
class RaceCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
||||||
bool mPlayable;
|
bool mPlayable;
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that region records are internally consistent
|
/// \brief VerifyStage: make sure that region records are internally consistent
|
||||||
class RegionCheckStage : public Stage
|
class RegionCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Region>& mRegions;
|
const CSMWorld::IdCollection<ESM::Region>& mRegions;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that skill records are internally consistent
|
/// \brief VerifyStage: make sure that skill records are internally consistent
|
||||||
class SkillCheckStage : public Stage
|
class SkillCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
|
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that sound records are internally consistent
|
/// \brief VerifyStage: make sure that sound records are internally consistent
|
||||||
class SoundCheckStage : public Stage
|
class SoundCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
|
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that spell records are internally consistent
|
/// \brief VerifyStage: make sure that spell records are internally consistent
|
||||||
class SpellCheckStage : public Stage
|
class SpellCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
|
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
#include "stage.hpp"
|
|
||||||
|
|
||||||
CSMTools::Stage::~Stage() {}
|
|
|
@ -3,9 +3,8 @@
|
||||||
|
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
|
||||||
#include "verifier.hpp"
|
|
||||||
|
|
||||||
#include "../doc/state.hpp"
|
#include "../doc/state.hpp"
|
||||||
|
#include "../doc/operation.hpp"
|
||||||
|
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
@ -21,7 +20,7 @@
|
||||||
#include "birthsigncheck.hpp"
|
#include "birthsigncheck.hpp"
|
||||||
#include "spellcheck.hpp"
|
#include "spellcheck.hpp"
|
||||||
|
|
||||||
CSMTools::Operation *CSMTools::Tools::get (int type)
|
CSMDoc::Operation *CSMTools::Tools::get (int type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -31,19 +30,19 @@ CSMTools::Operation *CSMTools::Tools::get (int type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSMTools::Operation *CSMTools::Tools::get (int type) const
|
const CSMDoc::Operation *CSMTools::Tools::get (int type) const
|
||||||
{
|
{
|
||||||
return const_cast<Tools *> (this)->get (type);
|
return const_cast<Tools *> (this)->get (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::Verifier *CSMTools::Tools::getVerifier()
|
CSMDoc::Operation *CSMTools::Tools::getVerifier()
|
||||||
{
|
{
|
||||||
if (!mVerifier)
|
if (!mVerifier)
|
||||||
{
|
{
|
||||||
mVerifier = new Verifier;
|
mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
|
||||||
|
|
||||||
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||||
connect (mVerifier, SIGNAL (finished()), this, SLOT (verifierDone()));
|
connect (mVerifier, SIGNAL (done (int)), this, SIGNAL (done (int)));
|
||||||
connect (mVerifier, SIGNAL (reportMessage (const QString&, int)),
|
connect (mVerifier, SIGNAL (reportMessage (const QString&, int)),
|
||||||
this, SLOT (verifierMessage (const QString&, int)));
|
this, SLOT (verifierMessage (const QString&, int)));
|
||||||
|
|
||||||
|
@ -103,7 +102,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier()
|
||||||
|
|
||||||
void CSMTools::Tools::abortOperation (int type)
|
void CSMTools::Tools::abortOperation (int type)
|
||||||
{
|
{
|
||||||
if (Operation *operation = get (type))
|
if (CSMDoc::Operation *operation = get (type))
|
||||||
operation->abort();
|
operation->abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +117,7 @@ int CSMTools::Tools::getRunningOperations() const
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
for (int i=0; sOperations[i]!=-1; ++i)
|
for (int i=0; sOperations[i]!=-1; ++i)
|
||||||
if (const Operation *operation = get (sOperations[i]))
|
if (const CSMDoc::Operation *operation = get (sOperations[i]))
|
||||||
if (operation->isRunning())
|
if (operation->isRunning())
|
||||||
result |= sOperations[i];
|
result |= sOperations[i];
|
||||||
|
|
||||||
|
@ -133,11 +132,6 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId&
|
||||||
return mReports.at (id.getIndex());
|
return mReports.at (id.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Tools::verifierDone()
|
|
||||||
{
|
|
||||||
emit done (CSMDoc::State_Verifying);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMTools::Tools::verifierMessage (const QString& message, int type)
|
void CSMTools::Tools::verifierMessage (const QString& message, int type)
|
||||||
{
|
{
|
||||||
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
||||||
|
|
|
@ -11,10 +11,13 @@ namespace CSMWorld
|
||||||
class UniversalId;
|
class UniversalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Operation;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
class Verifier;
|
|
||||||
class Operation;
|
|
||||||
class ReportModel;
|
class ReportModel;
|
||||||
|
|
||||||
class Tools : public QObject
|
class Tools : public QObject
|
||||||
|
@ -22,7 +25,7 @@ namespace CSMTools
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
CSMWorld::Data& mData;
|
CSMWorld::Data& mData;
|
||||||
Verifier *mVerifier;
|
CSMDoc::Operation *mVerifier;
|
||||||
std::map<int, ReportModel *> mReports;
|
std::map<int, ReportModel *> mReports;
|
||||||
int mNextReportNumber;
|
int mNextReportNumber;
|
||||||
std::map<int, int> mActiveReports; // type, report number
|
std::map<int, int> mActiveReports; // type, report number
|
||||||
|
@ -31,12 +34,12 @@ namespace CSMTools
|
||||||
Tools (const Tools&);
|
Tools (const Tools&);
|
||||||
Tools& operator= (const Tools&);
|
Tools& operator= (const Tools&);
|
||||||
|
|
||||||
Verifier *getVerifier();
|
CSMDoc::Operation *getVerifier();
|
||||||
|
|
||||||
Operation *get (int type);
|
CSMDoc::Operation *get (int type);
|
||||||
///< Returns a 0-pointer, if operation hasn't been used yet.
|
///< Returns a 0-pointer, if operation hasn't been used yet.
|
||||||
|
|
||||||
const Operation *get (int type) const;
|
const CSMDoc::Operation *get (int type) const;
|
||||||
///< Returns a 0-pointer, if operation hasn't been used yet.
|
///< Returns a 0-pointer, if operation hasn't been used yet.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -58,8 +61,6 @@ namespace CSMTools
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void verifierDone();
|
|
||||||
|
|
||||||
void verifierMessage (const QString& message, int type);
|
void verifierMessage (const QString& message, int type);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
#include "verifier.hpp"
|
|
||||||
|
|
||||||
#include "../doc/state.hpp"
|
|
||||||
|
|
||||||
CSMTools::Verifier::Verifier() : Operation (CSMDoc::State_Verifying)
|
|
||||||
{}
|
|
|
@ -1,17 +0,0 @@
|
||||||
#ifndef CSM_TOOLS_VERIFIER_H
|
|
||||||
#define CSM_TOOLS_VERIFIER_H
|
|
||||||
|
|
||||||
#include "operation.hpp"
|
|
||||||
|
|
||||||
namespace CSMTools
|
|
||||||
{
|
|
||||||
class Verifier : public Operation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Verifier();
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,6 +1,31 @@
|
||||||
|
|
||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
CSMWorld::CollectionBase::CollectionBase() {}
|
CSMWorld::CollectionBase::CollectionBase() {}
|
||||||
|
|
||||||
CSMWorld::CollectionBase::~CollectionBase() {}
|
CSMWorld::CollectionBase::~CollectionBase() {}
|
||||||
|
|
||||||
|
int CSMWorld::CollectionBase::searchColumnIndex (Columns::ColumnId id) const
|
||||||
|
{
|
||||||
|
int columns = getColumns();
|
||||||
|
|
||||||
|
for (int i=0; i<columns; ++i)
|
||||||
|
if (getColumn (i).mColumnId==id)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::CollectionBase::findColumnIndex (Columns::ColumnId id) const
|
||||||
|
{
|
||||||
|
int index = searchColumnIndex (id);
|
||||||
|
|
||||||
|
if (index==-1)
|
||||||
|
throw std::logic_error ("invalid column index");
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
|
#include "columns.hpp"
|
||||||
|
|
||||||
class QVariant;
|
class QVariant;
|
||||||
|
|
||||||
|
@ -83,6 +84,13 @@ namespace CSMWorld
|
||||||
///< Return a sorted collection of all IDs
|
///< Return a sorted collection of all IDs
|
||||||
///
|
///
|
||||||
/// \param listDeleted include deleted record in the list
|
/// \param listDeleted include deleted record in the list
|
||||||
|
|
||||||
|
int searchColumnIndex (Columns::ColumnId id) const;
|
||||||
|
///< Return index of column with the given \a id. If no such column exists, -1 is returned.
|
||||||
|
|
||||||
|
int findColumnIndex (Columns::ColumnId id) const;
|
||||||
|
///< Return index of column with the given \a id. If no such column exists, an exception is
|
||||||
|
/// thrown.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace CSMWorld
|
||||||
Display_CreatureType,
|
Display_CreatureType,
|
||||||
Display_WeaponType,
|
Display_WeaponType,
|
||||||
Display_RecordState,
|
Display_RecordState,
|
||||||
Display_RefRecordType
|
Display_RefRecordType,
|
||||||
|
Display_DialogueType
|
||||||
};
|
};
|
||||||
|
|
||||||
int mColumnId;
|
int mColumnId;
|
||||||
|
|
|
@ -1217,6 +1217,37 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct ScopeColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
ScopeColumn()
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_Scope, ColumnBase::Display_Integer, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int> (record.get().mScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
record2.mScope = static_cast<CSMFilter::Filter::Scope> (data.toInt());
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isUserEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
struct PosColumn : public Column<ESXRecordT>
|
struct PosColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
|
@ -1284,6 +1315,39 @@ namespace CSMWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct DialogueTypeColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
DialogueTypeColumn (bool hidden = false)
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_DialogueType, ColumnBase::Display_DialogueType,
|
||||||
|
hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int> (record.get().mType);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
record2.mType = data.toInt();
|
||||||
|
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isUserEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -159,6 +159,8 @@ namespace CSMWorld
|
||||||
{ ColumnId_DoorPositionXRot, "Teleport Rot X" },
|
{ ColumnId_DoorPositionXRot, "Teleport Rot X" },
|
||||||
{ ColumnId_DoorPositionYRot, "Teleport Rot Y" },
|
{ ColumnId_DoorPositionYRot, "Teleport Rot Y" },
|
||||||
{ ColumnId_DoorPositionZRot, "Teleport Rot Z" },
|
{ ColumnId_DoorPositionZRot, "Teleport Rot Z" },
|
||||||
|
{ ColumnId_DialogueType, "Dialogue Type" },
|
||||||
|
{ ColumnId_Scope, "Scope", },
|
||||||
|
|
||||||
{ ColumnId_UseValue1, "Use value 1" },
|
{ ColumnId_UseValue1, "Use value 1" },
|
||||||
{ ColumnId_UseValue2, "Use value 2" },
|
{ ColumnId_UseValue2, "Use value 2" },
|
||||||
|
@ -269,6 +271,11 @@ namespace
|
||||||
"unknown", "none", "short", "integer", "long", "float", "string", 0
|
"unknown", "none", "short", "integer", "long", "float", "string", 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *sDialogueTypeEnums[] =
|
||||||
|
{
|
||||||
|
"Topic", "Voice", "Greeting", "Persuasion", 0
|
||||||
|
};
|
||||||
|
|
||||||
const char **getEnumNames (CSMWorld::Columns::ColumnId column)
|
const char **getEnumNames (CSMWorld::Columns::ColumnId column)
|
||||||
{
|
{
|
||||||
switch (column)
|
switch (column)
|
||||||
|
@ -283,6 +290,7 @@ namespace
|
||||||
case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes;
|
case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes;
|
||||||
case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums;
|
case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums;
|
||||||
case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums;
|
case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums;
|
||||||
|
case CSMWorld::Columns::ColumnId_DialogueType: return sDialogueTypeEnums;
|
||||||
|
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,8 @@ namespace CSMWorld
|
||||||
ColumnId_DoorPositionXRot = 139,
|
ColumnId_DoorPositionXRot = 139,
|
||||||
ColumnId_DoorPositionYRot = 140,
|
ColumnId_DoorPositionYRot = 140,
|
||||||
ColumnId_DoorPositionZRot = 141,
|
ColumnId_DoorPositionZRot = 141,
|
||||||
|
ColumnId_DialogueType = 142,
|
||||||
|
ColumnId_Scope = 143,
|
||||||
|
|
||||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||||
// to extend the number of use values.
|
// to extend the number of use values.
|
||||||
|
|
|
@ -44,6 +44,17 @@ void CSMWorld::Data::appendIds (std::vector<std::string>& ids, const CollectionB
|
||||||
ids.insert (ids.end(), ids2.begin(), ids2.end());
|
ids.insert (ids.end(), ids2.begin(), ids2.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collection)
|
||||||
|
{
|
||||||
|
int number = 0;
|
||||||
|
|
||||||
|
for (int i=0; i<collection.getSize(); ++i)
|
||||||
|
if (collection.getRecord (i).mState==state)
|
||||||
|
++number;
|
||||||
|
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
CSMWorld::Data::Data() : mRefs (mCells)
|
CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
{
|
{
|
||||||
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
||||||
|
@ -141,6 +152,14 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_StarterSpell, 0x2));
|
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_StarterSpell, 0x2));
|
||||||
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AlwaysSucceeds, 0x4));
|
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AlwaysSucceeds, 0x4));
|
||||||
|
|
||||||
|
mTopics.addColumn (new StringIdColumn<ESM::Dialogue>);
|
||||||
|
mTopics.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
||||||
|
mTopics.addColumn (new DialogueTypeColumn<ESM::Dialogue>);
|
||||||
|
|
||||||
|
mJournals.addColumn (new StringIdColumn<ESM::Dialogue>);
|
||||||
|
mJournals.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
||||||
|
mJournals.addColumn (new DialogueTypeColumn<ESM::Dialogue> (true));
|
||||||
|
|
||||||
mCells.addColumn (new StringIdColumn<Cell>);
|
mCells.addColumn (new StringIdColumn<Cell>);
|
||||||
mCells.addColumn (new RecordStateColumn<Cell>);
|
mCells.addColumn (new RecordStateColumn<Cell>);
|
||||||
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_Cell));
|
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_Cell));
|
||||||
|
@ -184,6 +203,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
|
||||||
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
|
||||||
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
|
||||||
|
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
|
||||||
|
|
||||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
||||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
||||||
|
@ -196,6 +216,8 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
|
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
|
||||||
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
|
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
|
||||||
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
|
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
|
||||||
|
addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic);
|
||||||
|
addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal);
|
||||||
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
|
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
|
||||||
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
|
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
|
||||||
UniversalId::Type_Referenceable);
|
UniversalId::Type_Referenceable);
|
||||||
|
@ -319,6 +341,28 @@ CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells()
|
||||||
return mSpells;
|
return mSpells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getTopics() const
|
||||||
|
{
|
||||||
|
return mTopics;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getTopics()
|
||||||
|
{
|
||||||
|
return mTopics;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getJournals() const
|
||||||
|
{
|
||||||
|
return mJournals;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getJournals()
|
||||||
|
{
|
||||||
|
return mJournals;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
|
const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
|
||||||
{
|
{
|
||||||
return mCells;
|
return mCells;
|
||||||
|
@ -387,7 +431,7 @@ void CSMWorld::Data::merge()
|
||||||
mGlobals.merge();
|
mGlobals.merge();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base, bool project)
|
||||||
{
|
{
|
||||||
ESM::ESMReader reader;
|
ESM::ESMReader reader;
|
||||||
|
|
||||||
|
@ -397,6 +441,9 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
||||||
|
|
||||||
reader.open (path.string());
|
reader.open (path.string());
|
||||||
|
|
||||||
|
mAuthor = reader.getAuthor();
|
||||||
|
mDescription = reader.getDesc();
|
||||||
|
|
||||||
// Note: We do not need to send update signals here, because at this point the model is not connected
|
// Note: We do not need to send update signals here, because at this point the model is not connected
|
||||||
// to any view.
|
// to any view.
|
||||||
while (reader.hasMoreRecs())
|
while (reader.hasMoreRecs())
|
||||||
|
@ -447,6 +494,54 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
||||||
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
|
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
|
||||||
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
|
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
|
||||||
|
|
||||||
|
case ESM::REC_DIAL:
|
||||||
|
{
|
||||||
|
std::string id = reader.getHNOString ("NAME");
|
||||||
|
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = id;
|
||||||
|
record.load (reader);
|
||||||
|
|
||||||
|
if (record.mType==ESM::Dialogue::Journal)
|
||||||
|
{
|
||||||
|
mJournals.load (record, base);
|
||||||
|
}
|
||||||
|
else if (record.mType==ESM::Dialogue::Deleted)
|
||||||
|
{
|
||||||
|
if (mJournals.tryDelete (id))
|
||||||
|
{
|
||||||
|
/// \todo handle info records
|
||||||
|
}
|
||||||
|
else if (mTopics.tryDelete (id))
|
||||||
|
{
|
||||||
|
/// \todo handle info records
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// \todo report deletion of non-existing record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTopics.load (record, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ESM::REC_FILT:
|
||||||
|
|
||||||
|
if (project)
|
||||||
|
{
|
||||||
|
mFilters.load (reader, base);
|
||||||
|
mFilters.setData (mFilters.getSize()-1,
|
||||||
|
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
|
||||||
|
static_cast<int> (CSMFilter::Filter::Scope_Project));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall through (filter record in a content file is an error with format 0)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/// \todo throw an exception instead, once all records are implemented
|
/// \todo throw an exception instead, once all records are implemented
|
||||||
|
@ -469,10 +564,50 @@ bool CSMWorld::Data::hasId (const std::string& id) const
|
||||||
getRegions().searchId (id)!=-1 ||
|
getRegions().searchId (id)!=-1 ||
|
||||||
getBirthsigns().searchId (id)!=-1 ||
|
getBirthsigns().searchId (id)!=-1 ||
|
||||||
getSpells().searchId (id)!=-1 ||
|
getSpells().searchId (id)!=-1 ||
|
||||||
|
getTopics().searchId (id)!=-1 ||
|
||||||
|
getJournals().searchId (id)!=-1 ||
|
||||||
getCells().searchId (id)!=-1 ||
|
getCells().searchId (id)!=-1 ||
|
||||||
getReferenceables().searchId (id)!=-1;
|
getReferenceables().searchId (id)!=-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CSMWorld::Data::count (RecordBase::State state) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
count (state, mGlobals) +
|
||||||
|
count (state, mGmsts) +
|
||||||
|
count (state, mSkills) +
|
||||||
|
count (state, mClasses) +
|
||||||
|
count (state, mFactions) +
|
||||||
|
count (state, mRaces) +
|
||||||
|
count (state, mSounds) +
|
||||||
|
count (state, mScripts) +
|
||||||
|
count (state, mRegions) +
|
||||||
|
count (state, mBirthsigns) +
|
||||||
|
count (state, mSpells) +
|
||||||
|
count (state, mCells) +
|
||||||
|
count (state, mReferenceables);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::setDescription (const std::string& description)
|
||||||
|
{
|
||||||
|
mDescription = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMWorld::Data::getDescription() const
|
||||||
|
{
|
||||||
|
return mDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::setAuthor (const std::string& author)
|
||||||
|
{
|
||||||
|
mAuthor = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMWorld::Data::getAuthor() const
|
||||||
|
{
|
||||||
|
return mAuthor;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> ids;
|
std::vector<std::string> ids;
|
||||||
|
@ -487,6 +622,8 @@ std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
||||||
appendIds (ids, mRegions, listDeleted);
|
appendIds (ids, mRegions, listDeleted);
|
||||||
appendIds (ids, mBirthsigns, listDeleted);
|
appendIds (ids, mBirthsigns, listDeleted);
|
||||||
appendIds (ids, mSpells, listDeleted);
|
appendIds (ids, mSpells, listDeleted);
|
||||||
|
appendIds (ids, mTopics, listDeleted);
|
||||||
|
appendIds (ids, mJournals, listDeleted);
|
||||||
appendIds (ids, mCells, listDeleted);
|
appendIds (ids, mCells, listDeleted);
|
||||||
appendIds (ids, mReferenceables, listDeleted);
|
appendIds (ids, mReferenceables, listDeleted);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <components/esm/loadregn.hpp>
|
#include <components/esm/loadregn.hpp>
|
||||||
#include <components/esm/loadbsgn.hpp>
|
#include <components/esm/loadbsgn.hpp>
|
||||||
#include <components/esm/loadspel.hpp>
|
#include <components/esm/loadspel.hpp>
|
||||||
|
#include <components/esm/loaddial.hpp>
|
||||||
|
|
||||||
#include "../filter/filter.hpp"
|
#include "../filter/filter.hpp"
|
||||||
|
|
||||||
|
@ -48,12 +49,16 @@ namespace CSMWorld
|
||||||
IdCollection<ESM::Region> mRegions;
|
IdCollection<ESM::Region> mRegions;
|
||||||
IdCollection<ESM::BirthSign> mBirthsigns;
|
IdCollection<ESM::BirthSign> mBirthsigns;
|
||||||
IdCollection<ESM::Spell> mSpells;
|
IdCollection<ESM::Spell> mSpells;
|
||||||
|
IdCollection<ESM::Dialogue> mTopics;
|
||||||
|
IdCollection<ESM::Dialogue> mJournals;
|
||||||
IdCollection<Cell> mCells;
|
IdCollection<Cell> mCells;
|
||||||
RefIdCollection mReferenceables;
|
RefIdCollection mReferenceables;
|
||||||
RefCollection mRefs;
|
RefCollection mRefs;
|
||||||
IdCollection<CSMFilter::Filter> mFilters;
|
IdCollection<CSMFilter::Filter> mFilters;
|
||||||
std::vector<QAbstractItemModel *> mModels;
|
std::vector<QAbstractItemModel *> mModels;
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||||
|
std::string mAuthor;
|
||||||
|
std::string mDescription;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Data (const Data&);
|
Data (const Data&);
|
||||||
|
@ -66,6 +71,8 @@ namespace CSMWorld
|
||||||
bool listDeleted);
|
bool listDeleted);
|
||||||
///< Append all IDs from collection to \a ids.
|
///< Append all IDs from collection to \a ids.
|
||||||
|
|
||||||
|
static int count (RecordBase::State state, const CollectionBase& collection);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Data();
|
Data();
|
||||||
|
@ -116,6 +123,14 @@ namespace CSMWorld
|
||||||
|
|
||||||
IdCollection<ESM::Spell>& getSpells();
|
IdCollection<ESM::Spell>& getSpells();
|
||||||
|
|
||||||
|
const IdCollection<ESM::Dialogue>& getTopics() const;
|
||||||
|
|
||||||
|
IdCollection<ESM::Dialogue>& getTopics();
|
||||||
|
|
||||||
|
const IdCollection<ESM::Dialogue>& getJournals() const;
|
||||||
|
|
||||||
|
IdCollection<ESM::Dialogue>& getJournals();
|
||||||
|
|
||||||
const IdCollection<Cell>& getCells() const;
|
const IdCollection<Cell>& getCells() const;
|
||||||
|
|
||||||
IdCollection<Cell>& getCells();
|
IdCollection<Cell>& getCells();
|
||||||
|
@ -141,8 +156,10 @@ namespace CSMWorld
|
||||||
void merge();
|
void merge();
|
||||||
///< Merge modified into base.
|
///< Merge modified into base.
|
||||||
|
|
||||||
void loadFile (const boost::filesystem::path& path, bool base);
|
void loadFile (const boost::filesystem::path& path, bool base, bool project);
|
||||||
///< Merging content of a file into base or modified.
|
///< Merging content of a file into base or modified.
|
||||||
|
///
|
||||||
|
/// \param project load project file instead of content file
|
||||||
|
|
||||||
bool hasId (const std::string& id) const;
|
bool hasId (const std::string& id) const;
|
||||||
|
|
||||||
|
@ -151,6 +168,17 @@ namespace CSMWorld
|
||||||
///
|
///
|
||||||
/// \param listDeleted include deleted record in the list
|
/// \param listDeleted include deleted record in the list
|
||||||
|
|
||||||
|
int count (RecordBase::State state) const;
|
||||||
|
///< Return number of top-level records with the given \a state.
|
||||||
|
|
||||||
|
void setDescription (const std::string& description);
|
||||||
|
|
||||||
|
std::string getDescription() const;
|
||||||
|
|
||||||
|
void setAuthor (const std::string& author);
|
||||||
|
|
||||||
|
std::string getAuthor() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void idListChanged();
|
void idListChanged();
|
||||||
|
|
|
@ -7,21 +7,24 @@
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
/// \brief Single type collection of top level records
|
/// \brief Single type collection of top level records
|
||||||
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||||
class IdCollection : public Collection<ESXRecordT, IdAccessorT>
|
class IdCollection : public Collection<ESXRecordT, IdAccessorT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void load (ESM::ESMReader& reader, bool base,
|
void load (ESM::ESMReader& reader, bool base);
|
||||||
UniversalId::Type type = UniversalId::Type_None);
|
|
||||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
void load (const ESXRecordT& record, bool base);
|
||||||
|
|
||||||
|
bool tryDelete (const std::string& id);
|
||||||
|
///< Try deleting \a id. If the id does not exist or can't be deleted the call is ignored.
|
||||||
|
///
|
||||||
|
/// \return Has the ID been deleted?
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base,
|
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base)
|
||||||
UniversalId::Type type)
|
|
||||||
{
|
{
|
||||||
std::string id = reader.getHNOString ("NAME");
|
std::string id = reader.getHNOString ("NAME");
|
||||||
|
|
||||||
|
@ -56,31 +59,63 @@ namespace CSMWorld
|
||||||
IdAccessorT().getId (record) = id;
|
IdAccessorT().getId (record) = id;
|
||||||
record.load (reader);
|
record.load (reader);
|
||||||
|
|
||||||
int index = this->searchId (IdAccessorT().getId (record));
|
load (record, base);
|
||||||
|
|
||||||
if (index==-1)
|
|
||||||
{
|
|
||||||
// new record
|
|
||||||
Record<ESXRecordT> record2;
|
|
||||||
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
|
||||||
(base ? record2.mBase : record2.mModified) = record;
|
|
||||||
|
|
||||||
this->appendRecord (record2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// old record
|
|
||||||
Record<ESXRecordT> record2 = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
|
|
||||||
|
|
||||||
if (base)
|
|
||||||
record2.mBase = record;
|
|
||||||
else
|
|
||||||
record2.setModified (record);
|
|
||||||
|
|
||||||
this->setRecord (index, record2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void IdCollection<ESXRecordT, IdAccessorT>::load (const ESXRecordT& record, bool base)
|
||||||
|
{
|
||||||
|
int index = this->searchId (IdAccessorT().getId (record));
|
||||||
|
|
||||||
|
if (index==-1)
|
||||||
|
{
|
||||||
|
// new record
|
||||||
|
Record<ESXRecordT> record2;
|
||||||
|
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
||||||
|
(base ? record2.mBase : record2.mModified) = record;
|
||||||
|
|
||||||
|
this->appendRecord (record2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// old record
|
||||||
|
Record<ESXRecordT> record2 = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
|
||||||
|
|
||||||
|
if (base)
|
||||||
|
record2.mBase = record;
|
||||||
|
else
|
||||||
|
record2.setModified (record);
|
||||||
|
|
||||||
|
this->setRecord (index, record2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
bool IdCollection<ESXRecordT, IdAccessorT>::tryDelete (const std::string& id)
|
||||||
|
{
|
||||||
|
int index = this->searchId (id);
|
||||||
|
|
||||||
|
if (index==-1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Record<ESXRecordT> record = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
|
||||||
|
|
||||||
|
if (record.isDeleted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (record.mState==RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::removeRows (index, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
record.mState = RecordBase::State_Deleted;
|
||||||
|
this->setRecord (index, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -161,21 +161,10 @@ const CSMWorld::RecordBase& CSMWorld::IdTable::getRecord (const std::string& id)
|
||||||
|
|
||||||
int CSMWorld::IdTable::searchColumnIndex (Columns::ColumnId id) const
|
int CSMWorld::IdTable::searchColumnIndex (Columns::ColumnId id) const
|
||||||
{
|
{
|
||||||
int columns = mIdCollection->getColumns();
|
return mIdCollection->searchColumnIndex (id);
|
||||||
|
|
||||||
for (int i=0; i<columns; ++i)
|
|
||||||
if (mIdCollection->getColumn (i).mColumnId==id)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CSMWorld::IdTable::findColumnIndex (Columns::ColumnId id) const
|
int CSMWorld::IdTable::findColumnIndex (Columns::ColumnId id) const
|
||||||
{
|
{
|
||||||
int index = searchColumnIndex (id);
|
return mIdCollection->findColumnIndex (id);
|
||||||
|
|
||||||
if (index==-1)
|
|
||||||
throw std::logic_error ("invalid column index");
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
}
|
|
@ -539,3 +539,8 @@ std::vector<std::string> CSMWorld::RefIdCollection::getIds (bool listDeleted) co
|
||||||
{
|
{
|
||||||
return mData.getIds (listDeleted);
|
return mData.getIds (listDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::RefIdCollection::save (int index, ESM::ESMWriter& writer) const
|
||||||
|
{
|
||||||
|
mData.save (index, writer);
|
||||||
|
}
|
|
@ -9,6 +9,11 @@
|
||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
#include "refiddata.hpp"
|
#include "refiddata.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMWriter;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class RefIdAdapter;
|
class RefIdAdapter;
|
||||||
|
@ -94,6 +99,8 @@ namespace CSMWorld
|
||||||
///< Return a sorted collection of all IDs
|
///< Return a sorted collection of all IDs
|
||||||
///
|
///
|
||||||
/// \param listDeleted include deleted record in the list
|
/// \param listDeleted include deleted record in the list
|
||||||
|
|
||||||
|
void save (int index, ESM::ESMWriter& writer) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,3 +218,16 @@ std::vector<std::string> CSMWorld::RefIdData::getIds (bool listDeleted) const
|
||||||
|
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::RefIdData::save (int index, ESM::ESMWriter& writer) const
|
||||||
|
{
|
||||||
|
LocalIndex localIndex = globalToLocalIndex (index);
|
||||||
|
|
||||||
|
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter =
|
||||||
|
mRecordContainers.find (localIndex.second);
|
||||||
|
|
||||||
|
if (iter==mRecordContainers.end())
|
||||||
|
throw std::logic_error ("invalid local index type");
|
||||||
|
|
||||||
|
iter->second->save (localIndex.first, writer);
|
||||||
|
}
|
|
@ -23,6 +23,7 @@
|
||||||
#include <components/esm/loadweap.hpp>
|
#include <components/esm/loadweap.hpp>
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
#include <components/esm/loadmisc.hpp>
|
#include <components/esm/loadmisc.hpp>
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
|
@ -51,6 +52,8 @@ namespace CSMWorld
|
||||||
virtual void erase (int index, int count) = 0;
|
virtual void erase (int index, int count) = 0;
|
||||||
|
|
||||||
virtual std::string getId (int index) const = 0;
|
virtual std::string getId (int index) const = 0;
|
||||||
|
|
||||||
|
virtual void save (int index, ESM::ESMWriter& writer) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RecordT>
|
template<typename RecordT>
|
||||||
|
@ -71,6 +74,8 @@ namespace CSMWorld
|
||||||
virtual void erase (int index, int count);
|
virtual void erase (int index, int count);
|
||||||
|
|
||||||
virtual std::string getId (int index) const;
|
virtual std::string getId (int index) const;
|
||||||
|
|
||||||
|
virtual void save (int index, ESM::ESMWriter& writer) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RecordT>
|
template<typename RecordT>
|
||||||
|
@ -123,6 +128,31 @@ namespace CSMWorld
|
||||||
return mContainer.at (index).get().mId;
|
return mContainer.at (index).get().mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename RecordT>
|
||||||
|
void RefIdDataContainer<RecordT>::save (int index, ESM::ESMWriter& writer) const
|
||||||
|
{
|
||||||
|
CSMWorld::RecordBase::State state = mContainer.at (index).mState;
|
||||||
|
|
||||||
|
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||||
|
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
std::string type;
|
||||||
|
for (int i=0; i<4; ++i)
|
||||||
|
/// \todo make endianess agnostic (change ESMWriter interface?)
|
||||||
|
type += reinterpret_cast<const char *> (&mContainer.at (index).mModified.sRecordId)[i];
|
||||||
|
|
||||||
|
writer.startRecord (type);
|
||||||
|
writer.writeHNCString ("NAME", getId (index));
|
||||||
|
mContainer.at (index).mModified.save (writer);
|
||||||
|
writer.endRecord (type);
|
||||||
|
}
|
||||||
|
else if (state==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
{
|
||||||
|
/// \todo write record with delete flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class RefIdData
|
class RefIdData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -187,6 +217,8 @@ namespace CSMWorld
|
||||||
///< Return a sorted collection of all IDs
|
///< Return a sorted collection of all IDs
|
||||||
///
|
///
|
||||||
/// \param listDeleted include deleted record in the list
|
/// \param listDeleted include deleted record in the list
|
||||||
|
|
||||||
|
void save (int index, ESM::ESMWriter& writer) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ namespace
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
|
||||||
"Referenceables", 0 },
|
"Referenceables", 0 },
|
||||||
|
@ -54,6 +56,8 @@ namespace
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
||||||
|
|
|
@ -87,6 +87,10 @@ namespace CSMWorld
|
||||||
Type_RegionMap,
|
Type_RegionMap,
|
||||||
Type_Filter,
|
Type_Filter,
|
||||||
Type_Filters,
|
Type_Filters,
|
||||||
|
Type_Topics,
|
||||||
|
Type_Topic,
|
||||||
|
Type_Journals,
|
||||||
|
Type_Journal,
|
||||||
Type_Scene
|
Type_Scene
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
|
|
||||||
CSVDoc::AdjusterWidget::AdjusterWidget (QWidget *parent)
|
CSVDoc::AdjusterWidget::AdjusterWidget (QWidget *parent)
|
||||||
: QWidget (parent), mValid (false)
|
: QWidget (parent), mValid (false), mAction (ContentAction_Undefined)
|
||||||
{
|
{
|
||||||
QHBoxLayout *layout = new QHBoxLayout (this);
|
QHBoxLayout *layout = new QHBoxLayout (this);
|
||||||
|
|
||||||
|
@ -30,6 +30,11 @@ CSVDoc::AdjusterWidget::AdjusterWidget (QWidget *parent)
|
||||||
setLayout (layout);
|
setLayout (layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::AdjusterWidget::setAction (ContentAction action)
|
||||||
|
{
|
||||||
|
mAction = action;
|
||||||
|
}
|
||||||
|
|
||||||
void CSVDoc::AdjusterWidget::setLocalData (const boost::filesystem::path& localData)
|
void CSVDoc::AdjusterWidget::setLocalData (const boost::filesystem::path& localData)
|
||||||
{
|
{
|
||||||
mLocalData = localData;
|
mLocalData = localData;
|
||||||
|
@ -43,41 +48,60 @@ boost::filesystem::path CSVDoc::AdjusterWidget::getPath() const
|
||||||
return mResultPath;
|
return mResultPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSVDoc::AdjusterWidget::isValid() const
|
||||||
|
{
|
||||||
|
return mValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::AdjusterWidget::setFilenameCheck (bool doCheck)
|
||||||
|
{
|
||||||
|
mDoFilenameCheck = doCheck;
|
||||||
|
}
|
||||||
|
|
||||||
void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
|
void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
|
||||||
{
|
{
|
||||||
QString message;
|
QString message;
|
||||||
|
|
||||||
if (name.isEmpty())
|
mValid = (!name.isEmpty());
|
||||||
|
|
||||||
|
if (!mValid)
|
||||||
{
|
{
|
||||||
mValid = false;
|
|
||||||
message = "No name.";
|
message = "No name.";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
boost::filesystem::path path (name.toUtf8().data());
|
boost::filesystem::path path (name.toUtf8().data());
|
||||||
|
|
||||||
path.replace_extension (addon ? ".omwaddon" : ".omwgame");
|
bool isLegacyPath = (path.extension() == ".esm" ||
|
||||||
|
path.extension() == ".esp");
|
||||||
|
|
||||||
if (path.parent_path().string()==mLocalData.string())
|
bool isFilePathChanged = (path.parent_path().string() != mLocalData.string());
|
||||||
|
|
||||||
|
if (isLegacyPath)
|
||||||
|
path.replace_extension (addon ? ".omwaddon" : ".omwgame");
|
||||||
|
|
||||||
|
//if the file came from data-local and is not a legacy file to be converted,
|
||||||
|
//don't worry about doing a file check.
|
||||||
|
if (!isFilePathChanged && !isLegacyPath)
|
||||||
{
|
{
|
||||||
// path already points to the local data directory
|
// path already points to the local data directory
|
||||||
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str());
|
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str());
|
||||||
mResultPath = path;
|
mResultPath = path;
|
||||||
mValid = true;
|
|
||||||
}
|
}
|
||||||
|
//in all other cases, ensure the path points to data-local and do an existing file check
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// path points somewhere else or is a leaf name.
|
// path points somewhere else or is a leaf name.
|
||||||
path = mLocalData / path.filename();
|
if (isFilePathChanged)
|
||||||
|
path = mLocalData / path.filename();
|
||||||
|
|
||||||
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str());
|
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str());
|
||||||
mResultPath = path;
|
mResultPath = path;
|
||||||
mValid = true;
|
|
||||||
|
|
||||||
if (boost::filesystem::exists (path))
|
if (boost::filesystem::exists (path))
|
||||||
{
|
{
|
||||||
/// \todo add an user setting to make this an error.
|
/// \todo add an user setting to make this an error.
|
||||||
message += "<p>But a file with the same name already exists. If you continue, it will be overwritten.";
|
message += "<p>A file with the same name already exists. If you continue, it will be overwritten.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,21 +9,36 @@ class QLabel;
|
||||||
|
|
||||||
namespace CSVDoc
|
namespace CSVDoc
|
||||||
{
|
{
|
||||||
|
enum ContentAction
|
||||||
|
{
|
||||||
|
ContentAction_New,
|
||||||
|
ContentAction_Edit,
|
||||||
|
ContentAction_Undefined
|
||||||
|
};
|
||||||
|
|
||||||
class AdjusterWidget : public QWidget
|
class AdjusterWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
boost::filesystem::path mLocalData;
|
boost::filesystem::path mLocalData;
|
||||||
QLabel *mMessage;
|
QLabel *mMessage;
|
||||||
QLabel *mIcon;
|
QLabel *mIcon;
|
||||||
bool mValid;
|
bool mValid;
|
||||||
boost::filesystem::path mResultPath;
|
boost::filesystem::path mResultPath;
|
||||||
|
ContentAction mAction;
|
||||||
|
bool mDoFilenameCheck;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AdjusterWidget (QWidget *parent = 0);
|
AdjusterWidget (QWidget *parent = 0);
|
||||||
|
|
||||||
void setLocalData (const boost::filesystem::path& localData);
|
void setLocalData (const boost::filesystem::path& localData);
|
||||||
|
void setAction (ContentAction action);
|
||||||
|
|
||||||
|
void setFilenameCheck (bool doCheck);
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
boost::filesystem::path getPath() const;
|
boost::filesystem::path getPath() const;
|
||||||
///< This function must not be called if there is no valid path.
|
///< This function must not be called if there is no valid path.
|
||||||
|
|
|
@ -9,264 +9,166 @@
|
||||||
#include <QSpacerItem>
|
#include <QSpacerItem>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QGroupBox>
|
||||||
|
|
||||||
#include <components/fileorderlist/model/datafilesmodel.hpp>
|
#include "components/contentselector/model/esmfile.hpp"
|
||||||
#include <components/fileorderlist/model/pluginsproxymodel.hpp>
|
#include "components/contentselector/view/contentselector.hpp"
|
||||||
#include <components/fileorderlist/model/esm/esmfile.hpp>
|
|
||||||
|
|
||||||
#include <components/fileorderlist/utils/lineedit.hpp>
|
#include "filewidget.hpp"
|
||||||
|
#include "adjusterwidget.hpp"
|
||||||
|
|
||||||
FileDialog::FileDialog(QWidget *parent) :
|
CSVDoc::FileDialog::FileDialog(QWidget *parent) :
|
||||||
QDialog(parent)
|
QDialog(parent), mSelector (0), mFileWidget (0), mAdjusterWidget (0)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
ui.setupUi (this);
|
||||||
|
resize(400, 400);
|
||||||
|
|
||||||
// Models
|
setObjectName ("FileDialog");
|
||||||
mDataFilesModel = new DataFilesModel(this);
|
mSelector = new ContentSelectorView::ContentSelector (ui.contentSelectorWidget);
|
||||||
|
mAdjusterWidget = new AdjusterWidget (this);
|
||||||
mMastersProxyModel = new QSortFilterProxyModel();
|
|
||||||
mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm"));
|
|
||||||
mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
||||||
mMastersProxyModel->setSourceModel(mDataFilesModel);
|
|
||||||
|
|
||||||
mPluginsProxyModel = new PluginsProxyModel();
|
|
||||||
mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp"));
|
|
||||||
mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
||||||
mPluginsProxyModel->setSourceModel(mDataFilesModel);
|
|
||||||
|
|
||||||
mFilterProxyModel = new QSortFilterProxyModel();
|
|
||||||
mFilterProxyModel->setDynamicSortFilter(true);
|
|
||||||
mFilterProxyModel->setSourceModel(mPluginsProxyModel);
|
|
||||||
|
|
||||||
QCheckBox checkBox;
|
|
||||||
unsigned int height = checkBox.sizeHint().height() + 4;
|
|
||||||
|
|
||||||
mastersTable->setModel(mMastersProxyModel);
|
|
||||||
mastersTable->setObjectName("MastersTable");
|
|
||||||
mastersTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
mastersTable->setSortingEnabled(false);
|
|
||||||
mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
||||||
mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
||||||
mastersTable->setAlternatingRowColors(true);
|
|
||||||
mastersTable->horizontalHeader()->setStretchLastSection(true);
|
|
||||||
|
|
||||||
// Set the row height to the size of the checkboxes
|
|
||||||
mastersTable->verticalHeader()->setDefaultSectionSize(height);
|
|
||||||
mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
|
||||||
mastersTable->verticalHeader()->hide();
|
|
||||||
|
|
||||||
pluginsTable->setModel(mFilterProxyModel);
|
|
||||||
pluginsTable->setObjectName("PluginsTable");
|
|
||||||
pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
pluginsTable->setSortingEnabled(false);
|
|
||||||
pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
||||||
pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
||||||
pluginsTable->setAlternatingRowColors(true);
|
|
||||||
pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
|
|
||||||
pluginsTable->horizontalHeader()->setStretchLastSection(true);
|
|
||||||
|
|
||||||
pluginsTable->verticalHeader()->setDefaultSectionSize(height);
|
|
||||||
pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
|
||||||
|
|
||||||
// Hide the profile elements
|
|
||||||
profileLabel->hide();
|
|
||||||
profilesComboBox->hide();
|
|
||||||
newProfileButton->hide();
|
|
||||||
deleteProfileButton->hide();
|
|
||||||
|
|
||||||
// Add some extra widgets
|
|
||||||
QHBoxLayout *nameLayout = new QHBoxLayout();
|
|
||||||
QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
|
||||||
|
|
||||||
mNameLabel = new QLabel(tr("File Name:"), this);
|
|
||||||
|
|
||||||
QRegExpValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9\\s]*$"));
|
|
||||||
mNameLineEdit = new LineEdit(this);
|
|
||||||
mNameLineEdit->setValidator(validator);
|
|
||||||
|
|
||||||
nameLayout->addSpacerItem(spacer);
|
|
||||||
nameLayout->addWidget(mNameLabel);
|
|
||||||
nameLayout->addWidget(mNameLineEdit);
|
|
||||||
|
|
||||||
mButtonBox = new QDialogButtonBox(this);
|
|
||||||
|
|
||||||
mCreateButton = new QPushButton(tr("Create"), this);
|
|
||||||
mCreateButton->setEnabled(false);
|
|
||||||
|
|
||||||
verticalLayout->addLayout(nameLayout);
|
|
||||||
verticalLayout->addWidget(mButtonBox);
|
|
||||||
|
|
||||||
// Set sizes
|
|
||||||
QList<int> sizeList;
|
|
||||||
sizeList << 175;
|
|
||||||
sizeList << 200;
|
|
||||||
|
|
||||||
splitter->setSizes(sizeList);
|
|
||||||
|
|
||||||
resize(600, 400);
|
|
||||||
|
|
||||||
connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews()));
|
|
||||||
connect(mDataFilesModel, SIGNAL(checkedItemsChanged(QStringList)), this, SLOT(updateOpenButton(QStringList)));
|
|
||||||
connect(mNameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateCreateButton(QString)));
|
|
||||||
|
|
||||||
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
|
|
||||||
|
|
||||||
connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
|
||||||
connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
|
|
||||||
|
|
||||||
connect(mCreateButton, SIGNAL(clicked()), this, SLOT(createButtonClicked()));
|
|
||||||
|
|
||||||
connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
|
||||||
connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::updateViews()
|
void CSVDoc::FileDialog::addFiles(const QString &path)
|
||||||
{
|
{
|
||||||
// Ensure the columns are hidden because sort() re-enables them
|
mSelector->addFiles(path);
|
||||||
mastersTable->setColumnHidden(1, true);
|
|
||||||
mastersTable->setColumnHidden(3, true);
|
|
||||||
mastersTable->setColumnHidden(4, true);
|
|
||||||
mastersTable->setColumnHidden(5, true);
|
|
||||||
mastersTable->setColumnHidden(6, true);
|
|
||||||
mastersTable->setColumnHidden(7, true);
|
|
||||||
mastersTable->setColumnHidden(8, true);
|
|
||||||
mastersTable->resizeColumnsToContents();
|
|
||||||
|
|
||||||
pluginsTable->setColumnHidden(1, true);
|
|
||||||
pluginsTable->setColumnHidden(3, true);
|
|
||||||
pluginsTable->setColumnHidden(4, true);
|
|
||||||
pluginsTable->setColumnHidden(5, true);
|
|
||||||
pluginsTable->setColumnHidden(6, true);
|
|
||||||
pluginsTable->setColumnHidden(7, true);
|
|
||||||
pluginsTable->setColumnHidden(8, true);
|
|
||||||
pluginsTable->resizeColumnsToContents();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::updateOpenButton(const QStringList &items)
|
QStringList CSVDoc::FileDialog::selectedFilePaths()
|
||||||
{
|
{
|
||||||
QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open);
|
QStringList filePaths;
|
||||||
|
|
||||||
if (!openButton)
|
foreach (ContentSelectorModel::EsmFile *file, mSelector->selectedFiles() )
|
||||||
return;
|
filePaths.append(file->filePath());
|
||||||
|
|
||||||
openButton->setEnabled(!items.isEmpty());
|
return filePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::updateCreateButton(const QString &name)
|
void CSVDoc::FileDialog::setLocalData (const boost::filesystem::path& localData)
|
||||||
{
|
{
|
||||||
if (!mCreateButton->isVisible())
|
mAdjusterWidget->setLocalData (localData);
|
||||||
return;
|
|
||||||
|
|
||||||
mCreateButton->setEnabled(!name.isEmpty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::filterChanged(const QString &filter)
|
void CSVDoc::FileDialog::showDialog (ContentAction action)
|
||||||
{
|
{
|
||||||
QRegExp filterRe(filter, Qt::CaseInsensitive, QRegExp::FixedString);
|
mAction = action;
|
||||||
mFilterProxyModel->setFilterRegExp(filterRe);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileDialog::addFiles(const QString &path)
|
ui.projectGroupBoxLayout->insertWidget (0, mAdjusterWidget);
|
||||||
{
|
|
||||||
mDataFilesModel->addFiles(path);
|
|
||||||
mDataFilesModel->sort(3); // Sort by date accessed
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileDialog::setEncoding(const QString &encoding)
|
switch (mAction)
|
||||||
{
|
{
|
||||||
mDataFilesModel->setEncoding(encoding);
|
case ContentAction_New:
|
||||||
}
|
buildNewFileView();
|
||||||
|
break;
|
||||||
|
|
||||||
void FileDialog::setCheckState(QModelIndex index)
|
case ContentAction_Edit:
|
||||||
{
|
buildOpenFileView();
|
||||||
if (!index.isValid())
|
break;
|
||||||
return;
|
|
||||||
|
|
||||||
QObject *object = QObject::sender();
|
default:
|
||||||
|
break;
|
||||||
// Not a signal-slot call
|
|
||||||
if (!object)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
if (object->objectName() == QLatin1String("PluginsTable")) {
|
|
||||||
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
|
|
||||||
mFilterProxyModel->mapToSource(index));
|
|
||||||
|
|
||||||
if (sourceIndex.isValid()) {
|
|
||||||
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
|
||||||
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
|
|
||||||
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object->objectName() == QLatin1String("MastersTable")) {
|
mAdjusterWidget->setFilenameCheck (mAction == ContentAction_New);
|
||||||
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
|
|
||||||
|
|
||||||
if (sourceIndex.isValid()) {
|
//connections common to both dialog view flavors
|
||||||
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
|
connect (mSelector, SIGNAL (signalCurrentGamefileIndexChanged (int)),
|
||||||
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
|
this, SLOT (slotUpdateAcceptButton (int)));
|
||||||
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
connect (ui.projectButtonBox, SIGNAL (rejected()), this, SLOT (slotRejected()));
|
||||||
|
|
||||||
|
show();
|
||||||
|
raise();
|
||||||
|
activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FileDialog::checkedItemsPaths()
|
void CSVDoc::FileDialog::buildNewFileView()
|
||||||
{
|
{
|
||||||
return mDataFilesModel->checkedItemsPaths();
|
setWindowTitle(tr("Create a new addon"));
|
||||||
|
|
||||||
|
QPushButton* createButton = ui.projectButtonBox->button (QDialogButtonBox::Ok);
|
||||||
|
createButton->setText ("Create");
|
||||||
|
createButton->setEnabled (false);
|
||||||
|
|
||||||
|
mFileWidget = new FileWidget (this);
|
||||||
|
|
||||||
|
mFileWidget->setType (true);
|
||||||
|
mFileWidget->extensionLabelIsVisible(true);
|
||||||
|
|
||||||
|
ui.projectGroupBoxLayout->insertWidget (0, mFileWidget);
|
||||||
|
|
||||||
|
connect (mFileWidget, SIGNAL (nameChanged (const QString&, bool)),
|
||||||
|
mAdjusterWidget, SLOT (setName (const QString&, bool)));
|
||||||
|
|
||||||
|
connect (mFileWidget, SIGNAL (nameChanged(const QString &, bool)),
|
||||||
|
this, SLOT (slotUpdateAcceptButton(const QString &, bool)));
|
||||||
|
|
||||||
|
connect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotNewFile()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileDialog::fileName()
|
void CSVDoc::FileDialog::buildOpenFileView()
|
||||||
{
|
|
||||||
return mNameLineEdit->text();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileDialog::openFile()
|
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Open"));
|
setWindowTitle(tr("Open"));
|
||||||
|
ui.projectGroupBox->setTitle (QString(""));
|
||||||
|
|
||||||
mNameLabel->hide();
|
ui.projectButtonBox->button(QDialogButtonBox::Ok)->setEnabled (false);
|
||||||
mNameLineEdit->hide();
|
|
||||||
mCreateButton->hide();
|
|
||||||
|
|
||||||
mButtonBox->removeButton(mCreateButton);
|
connect (mSelector, SIGNAL (signalAddonFileSelected (int)), this, SLOT (slotUpdateAcceptButton (int)));
|
||||||
mButtonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Open);
|
connect (mSelector, SIGNAL (signalAddonFileUnselected (int)), this, SLOT (slotUpdateAcceptButton (int)));
|
||||||
QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open);
|
|
||||||
openButton->setEnabled(false);
|
|
||||||
|
|
||||||
show();
|
connect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotOpenFile()));
|
||||||
raise();
|
|
||||||
activateWindow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::newFile()
|
void CSVDoc::FileDialog::slotUpdateAcceptButton (int)
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("New"));
|
QString name = "";
|
||||||
|
|
||||||
mNameLabel->show();
|
if (mAction == ContentAction_New)
|
||||||
mNameLineEdit->clear();
|
name = mFileWidget->getName();
|
||||||
mNameLineEdit->show();
|
|
||||||
mCreateButton->show();
|
|
||||||
|
|
||||||
mButtonBox->setStandardButtons(QDialogButtonBox::Cancel);
|
slotUpdateAcceptButton (name, true);
|
||||||
mButtonBox->addButton(mCreateButton, QDialogButtonBox::ActionRole);
|
|
||||||
|
|
||||||
show();
|
|
||||||
raise();
|
|
||||||
activateWindow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::accept()
|
void CSVDoc::FileDialog::slotUpdateAcceptButton(const QString &name, bool)
|
||||||
{
|
{
|
||||||
emit openFiles();
|
bool success = (mSelector->selectedFiles().size() > 0);
|
||||||
|
|
||||||
|
bool isNew = (mAction == ContentAction_New);
|
||||||
|
|
||||||
|
if (isNew)
|
||||||
|
success = success && !(name.isEmpty());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back();
|
||||||
|
mAdjusterWidget->setName (file->filePath(), !file->isGameFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.projectButtonBox->button (QDialogButtonBox::Ok)->setEnabled (success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileDialog::createButtonClicked()
|
QString CSVDoc::FileDialog::filename() const
|
||||||
{
|
{
|
||||||
emit createNewFile();
|
if (mAction == ContentAction_New)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
return mSelector->currentFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::FileDialog::slotRejected()
|
||||||
|
{
|
||||||
|
emit rejected();
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::FileDialog::slotNewFile()
|
||||||
|
{
|
||||||
|
emit signalCreateNewFile (mAdjusterWidget->getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::FileDialog::slotOpenFile()
|
||||||
|
{
|
||||||
|
ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back();
|
||||||
|
|
||||||
|
mAdjusterWidget->setName (file->filePath(), !file->isGameFile());
|
||||||
|
|
||||||
|
emit signalOpenFiles (mAdjusterWidget->getPath());
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,63 +4,71 @@
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
|
|
||||||
#include "ui_datafilespage.h"
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include "adjusterwidget.hpp"
|
||||||
|
|
||||||
class QDialogButtonBox;
|
#ifndef CS_QT_BOOST_FILESYSTEM_PATH_DECLARED
|
||||||
class QSortFilterProxyModel;
|
#define CS_QT_BOOST_FILESYSTEM_PATH_DECLARED
|
||||||
class QAbstractItemModel;
|
Q_DECLARE_METATYPE (boost::filesystem::path)
|
||||||
class QPushButton;
|
#endif
|
||||||
class QStringList;
|
|
||||||
class QString;
|
#include "ui_filedialog.h"
|
||||||
class QMenu;
|
|
||||||
|
|
||||||
class DataFilesModel;
|
class DataFilesModel;
|
||||||
class PluginsProxyModel;
|
class PluginsProxyModel;
|
||||||
|
|
||||||
class FileDialog : public QDialog, private Ui::DataFilesPage
|
namespace ContentSelectorView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
class ContentSelector;
|
||||||
public:
|
}
|
||||||
explicit FileDialog(QWidget *parent = 0);
|
|
||||||
void addFiles(const QString &path);
|
|
||||||
void setEncoding(const QString &encoding);
|
|
||||||
|
|
||||||
void openFile();
|
namespace CSVDoc
|
||||||
void newFile();
|
{
|
||||||
void accepted();
|
class FileWidget;
|
||||||
|
|
||||||
QStringList checkedItemsPaths();
|
class FileDialog : public QDialog
|
||||||
QString fileName();
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
signals:
|
private:
|
||||||
void openFiles();
|
|
||||||
void createNewFile();
|
|
||||||
|
|
||||||
public slots:
|
ContentSelectorView::ContentSelector *mSelector;
|
||||||
void accept();
|
Ui::FileDialog ui;
|
||||||
|
ContentAction mAction;
|
||||||
|
FileWidget *mFileWidget;
|
||||||
|
AdjusterWidget *mAdjusterWidget;
|
||||||
|
|
||||||
private slots:
|
public:
|
||||||
void updateViews();
|
|
||||||
void updateOpenButton(const QStringList &items);
|
|
||||||
void updateCreateButton(const QString &name);
|
|
||||||
void setCheckState(QModelIndex index);
|
|
||||||
|
|
||||||
void filterChanged(const QString &filter);
|
explicit FileDialog(QWidget *parent = 0);
|
||||||
|
void showDialog (ContentAction action);
|
||||||
|
|
||||||
void createButtonClicked();
|
void addFiles (const QString &path);
|
||||||
|
|
||||||
private:
|
QString filename() const;
|
||||||
QLabel *mNameLabel;
|
QStringList selectedFilePaths();
|
||||||
LineEdit *mNameLineEdit;
|
|
||||||
|
|
||||||
QPushButton *mCreateButton;
|
void setLocalData (const boost::filesystem::path& localData);
|
||||||
QDialogButtonBox *mButtonBox;
|
|
||||||
|
|
||||||
DataFilesModel *mDataFilesModel;
|
private:
|
||||||
|
|
||||||
PluginsProxyModel *mPluginsProxyModel;
|
void buildNewFileView();
|
||||||
QSortFilterProxyModel *mMastersProxyModel;
|
void buildOpenFileView();
|
||||||
QSortFilterProxyModel *mFilterProxyModel;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void signalOpenFiles (const boost::filesystem::path &path);
|
||||||
|
void signalCreateNewFile (const boost::filesystem::path &path);
|
||||||
|
|
||||||
|
void signalUpdateAcceptButton (bool, int);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void slotNewFile();
|
||||||
|
void slotOpenFile();
|
||||||
|
void slotUpdateAcceptButton (int);
|
||||||
|
void slotUpdateAcceptButton (const QString &, bool);
|
||||||
|
void slotRejected();
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif // FILEDIALOG_HPP
|
#endif // FILEDIALOG_HPP
|
||||||
|
|
|
@ -51,3 +51,8 @@ void CSVDoc::FileWidget::textChanged (const QString& text)
|
||||||
{
|
{
|
||||||
emit nameChanged (getName(), mAddon);
|
emit nameChanged (getName(), mAddon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::FileWidget::extensionLabelIsVisible(bool visible)
|
||||||
|
{
|
||||||
|
mType->setVisible(visible);
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace CSVDoc
|
||||||
|
|
||||||
QString getName() const;
|
QString getName() const;
|
||||||
|
|
||||||
|
void extensionLabelIsVisible(bool visible);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void textChanged (const QString& text);
|
void textChanged (const QString& text);
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
|
||||||
|
#ifndef CS_QT_BOOST_FILESYSTEM_PATH_DECLARED
|
||||||
|
#define CS_QT_BOOST_FILESYSTEM_PATH_DECLARED
|
||||||
Q_DECLARE_METATYPE (boost::filesystem::path)
|
Q_DECLARE_METATYPE (boost::filesystem::path)
|
||||||
|
#endif
|
||||||
|
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,17 @@ CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2)
|
||||||
layout->addWidget (createButtons());
|
layout->addWidget (createButtons());
|
||||||
layout->addWidget (createTools());
|
layout->addWidget (createTools());
|
||||||
|
|
||||||
|
/// \todo remove this label once loading and saving are fully implemented
|
||||||
|
QLabel *warning = new QLabel ("<font color=Red>WARNING:<p>OpenCS is in alpha stage.<br>The code for loading and saving is incomplete.<br>This version of OpenCS is only a preview.<br>Do NOT use it for real editing!<br>You will lose records both on loading and on saving.<p>Please note:<br>If you lose data and come to the OpenMW forum to complain,<br>we will mock you.</font color>");
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
font.setPointSize (12);
|
||||||
|
font.setBold (true);
|
||||||
|
|
||||||
|
warning->setFont (font);
|
||||||
|
|
||||||
|
layout->addWidget (warning, 1);
|
||||||
|
|
||||||
setLayout (layout);
|
setLayout (layout);
|
||||||
|
|
||||||
QRect scr = QApplication::desktop()->screenGeometry();
|
QRect scr = QApplication::desktop()->screenGeometry();
|
||||||
|
|
|
@ -163,6 +163,14 @@ void CSVDoc::View::setupMechanicsMenu()
|
||||||
QAction *spells = new QAction (tr ("Spells"), this);
|
QAction *spells = new QAction (tr ("Spells"), this);
|
||||||
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
|
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
|
||||||
mechanics->addAction (spells);
|
mechanics->addAction (spells);
|
||||||
|
|
||||||
|
QAction *topics = new QAction (tr ("Topics"), this);
|
||||||
|
connect (topics, SIGNAL (triggered()), this, SLOT (addTopicsSubView()));
|
||||||
|
mechanics->addAction (topics);
|
||||||
|
|
||||||
|
QAction *journals = new QAction (tr ("Journals"), this);
|
||||||
|
connect (journals, SIGNAL (triggered()), this, SLOT (addJournalsSubView()));
|
||||||
|
mechanics->addAction (journals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::setupAssetsMenu()
|
void CSVDoc::View::setupAssetsMenu()
|
||||||
|
@ -412,6 +420,16 @@ void CSVDoc::View::addSceneSubView()
|
||||||
addSubView (CSMWorld::UniversalId::Type_Scene);
|
addSubView (CSMWorld::UniversalId::Type_Scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addTopicsSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Topics);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addJournalsSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Journals);
|
||||||
|
}
|
||||||
|
|
||||||
void CSVDoc::View::abortOperation (int type)
|
void CSVDoc::View::abortOperation (int type)
|
||||||
{
|
{
|
||||||
mDocument->abortOperation (type);
|
mDocument->abortOperation (type);
|
||||||
|
|
|
@ -166,6 +166,10 @@ namespace CSVDoc
|
||||||
|
|
||||||
void addSceneSubView();
|
void addSceneSubView();
|
||||||
|
|
||||||
|
void addTopicsSubView();
|
||||||
|
|
||||||
|
void addJournalsSubView();
|
||||||
|
|
||||||
void toggleShowStatusBar (bool show);
|
void toggleShowStatusBar (bool show);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
||||||
{ CSMWorld::ColumnBase::Display_ArmorType, CSMWorld::Columns::ColumnId_ArmorType, false },
|
{ CSMWorld::ColumnBase::Display_ArmorType, CSMWorld::Columns::ColumnId_ArmorType, false },
|
||||||
{ CSMWorld::ColumnBase::Display_ClothingType, CSMWorld::Columns::ColumnId_ClothingType, false },
|
{ CSMWorld::ColumnBase::Display_ClothingType, CSMWorld::Columns::ColumnId_ClothingType, false },
|
||||||
{ CSMWorld::ColumnBase::Display_CreatureType, CSMWorld::Columns::ColumnId_CreatureType, false },
|
{ CSMWorld::ColumnBase::Display_CreatureType, CSMWorld::Columns::ColumnId_CreatureType, false },
|
||||||
{ CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false }
|
{ CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false },
|
||||||
|
{ CSMWorld::ColumnBase::Display_DialogueType, CSMWorld::Columns::ColumnId_DialogueType, false }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)
|
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
#include "../../model/filter/filter.hpp"
|
#include "../../model/filter/filter.hpp"
|
||||||
|
|
||||||
|
#include "../../model/world/data.hpp"
|
||||||
|
#include "../../model/world/commands.hpp"
|
||||||
|
#include "../../model/world/columns.hpp"
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
|
||||||
std::string CSVFilter::FilterCreator::getNamespace() const
|
std::string CSVFilter::FilterCreator::getNamespace() const
|
||||||
{
|
{
|
||||||
switch (mScope->currentIndex())
|
switch (mScope->currentIndex())
|
||||||
|
@ -28,6 +33,15 @@ std::string CSVFilter::FilterCreator::getId() const
|
||||||
return getNamespace() + GenericCreator::getId();
|
return getNamespace() + GenericCreator::getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVFilter::FilterCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||||
|
{
|
||||||
|
int index =
|
||||||
|
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
|
||||||
|
findColumnIndex (CSMWorld::Columns::ColumnId_Scope);
|
||||||
|
|
||||||
|
command.addValue (index, mScope->currentIndex());
|
||||||
|
}
|
||||||
|
|
||||||
CSVFilter::FilterCreator::FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
CSVFilter::FilterCreator::FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
const CSMWorld::UniversalId& id)
|
const CSMWorld::UniversalId& id)
|
||||||
: GenericCreator (data, undoStack, id)
|
: GenericCreator (data, undoStack, id)
|
||||||
|
@ -39,7 +53,7 @@ CSVFilter::FilterCreator::FilterCreator (CSMWorld::Data& data, QUndoStack& undoS
|
||||||
|
|
||||||
mScope->addItem ("Project");
|
mScope->addItem ("Project");
|
||||||
mScope->addItem ("Session");
|
mScope->addItem ("Session");
|
||||||
/// \ŧodo re-enable for OpenMW 1.1
|
/// \todo re-enable for OpenMW 1.1
|
||||||
// mScope->addItem ("Content");
|
// mScope->addItem ("Content");
|
||||||
|
|
||||||
connect (mScope, SIGNAL (currentIndexChanged (int)), this, SLOT (setScope (int)));
|
connect (mScope, SIGNAL (currentIndexChanged (int)), this, SLOT (setScope (int)));
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace CSVFilter
|
||||||
|
|
||||||
virtual std::string getId() const;
|
virtual std::string getId() const;
|
||||||
|
|
||||||
|
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
|
35
apps/opencs/view/world/dialoguecreator.cpp
Normal file
35
apps/opencs/view/world/dialoguecreator.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
#include "dialoguecreator.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/loaddial.hpp>
|
||||||
|
|
||||||
|
#include "../../model/world/data.hpp"
|
||||||
|
#include "../../model/world/commands.hpp"
|
||||||
|
#include "../../model/world/columns.hpp"
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
|
||||||
|
void CSVWorld::DialogueCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||||
|
{
|
||||||
|
int index =
|
||||||
|
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
|
||||||
|
findColumnIndex (CSMWorld::Columns::ColumnId_DialogueType);
|
||||||
|
|
||||||
|
command.addValue (index, mType);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWorld::DialogueCreator::DialogueCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
const CSMWorld::UniversalId& id, int type)
|
||||||
|
: GenericCreator (data, undoStack, id), mType (type)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||||
|
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||||
|
{
|
||||||
|
return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||||
|
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||||
|
{
|
||||||
|
return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Journal);
|
||||||
|
}
|
41
apps/opencs/view/world/dialoguecreator.hpp
Normal file
41
apps/opencs/view/world/dialoguecreator.hpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef CSV_WORLD_DIALOGUECREATOR_H
|
||||||
|
#define CSV_WORLD_DIALOGUECREATOR_H
|
||||||
|
|
||||||
|
#include "genericcreator.hpp"
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
class DialogueCreator : public GenericCreator
|
||||||
|
{
|
||||||
|
int mType;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DialogueCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
const CSMWorld::UniversalId& id, int type);
|
||||||
|
};
|
||||||
|
|
||||||
|
class TopicCreatorFactory : public CreatorFactoryBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
const CSMWorld::UniversalId& id) const;
|
||||||
|
///< The ownership of the returned Creator is transferred to the caller.
|
||||||
|
};
|
||||||
|
|
||||||
|
class JournalCreatorFactory : public CreatorFactoryBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
const CSMWorld::UniversalId& id) const;
|
||||||
|
///< The ownership of the returned Creator is transferred to the caller.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -14,6 +14,7 @@
|
||||||
#include "referenceablecreator.hpp"
|
#include "referenceablecreator.hpp"
|
||||||
#include "referencecreator.hpp"
|
#include "referencecreator.hpp"
|
||||||
#include "scenesubview.hpp"
|
#include "scenesubview.hpp"
|
||||||
|
#include "dialoguecreator.hpp"
|
||||||
|
|
||||||
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +54,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
||||||
manager.add (CSMWorld::UniversalId::Type_References,
|
manager.add (CSMWorld::UniversalId::Type_References,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceCreator> >);
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceCreator> >);
|
||||||
|
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Topics,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, TopicCreatorFactory>);
|
||||||
|
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Journal,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, JournalCreatorFactory>);
|
||||||
|
|
||||||
// Subviews for editing/viewing individual records
|
// Subviews for editing/viewing individual records
|
||||||
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
|
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
|
||||||
|
|
||||||
|
|
|
@ -87,19 +87,33 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
|
||||||
{
|
{
|
||||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
||||||
|
|
||||||
|
// check record state
|
||||||
CSMWorld::RecordBase::State state =
|
CSMWorld::RecordBase::State state =
|
||||||
static_cast<CSMWorld::RecordBase::State> (
|
static_cast<CSMWorld::RecordBase::State> (
|
||||||
mModel->data (mModel->index (index.row(), 1)).toInt());
|
mModel->data (mModel->index (index.row(), 1)).toInt());
|
||||||
|
|
||||||
if (state!=CSMWorld::RecordBase::State_Deleted)
|
if (state==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// check other columns (only relevant for a subset of the tables)
|
||||||
|
int dialogueTypeIndex =
|
||||||
|
mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_DialogueType);
|
||||||
|
|
||||||
|
if (dialogueTypeIndex!=-1)
|
||||||
{
|
{
|
||||||
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
int type = mModel->data (mModel->index (index.row(), dialogueTypeIndex)).toInt();
|
||||||
|
|
||||||
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
|
if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal)
|
||||||
toString().toUtf8().constData();
|
continue;
|
||||||
|
|
||||||
deletableIds.push_back (id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add the id to the collection
|
||||||
|
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
||||||
|
|
||||||
|
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
|
||||||
|
toString().toUtf8().constData();
|
||||||
|
|
||||||
|
deletableIds.push_back (id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ add_openmw_dir (mwworld
|
||||||
cells localscripts customdata weather inventorystore ptr actionopen actionread
|
cells localscripts customdata weather inventorystore ptr actionopen actionread
|
||||||
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
||||||
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
||||||
|
contentloader esmloader omwloader
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwclass
|
add_openmw_dir (mwclass
|
||||||
|
|
|
@ -261,34 +261,14 @@ void OMW::Engine::setCell (const std::string& cellName)
|
||||||
mCellName = cellName;
|
mCellName = cellName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set master file (esm)
|
void OMW::Engine::addContentFile(const std::string& file)
|
||||||
// - If the given name does not have an extension, ".esm" is added automatically
|
|
||||||
|
|
||||||
void OMW::Engine::addMaster (const std::string& master)
|
|
||||||
{
|
{
|
||||||
mMaster.push_back(master);
|
if (file.find_last_of(".") == std::string::npos)
|
||||||
std::string &str = mMaster.back();
|
{
|
||||||
|
throw std::runtime_error("Missing extension in content file!");
|
||||||
|
}
|
||||||
|
|
||||||
// Append .esm if not already there
|
mContentFiles.push_back(file);
|
||||||
std::string::size_type sep = str.find_last_of (".");
|
|
||||||
if (sep == std::string::npos)
|
|
||||||
{
|
|
||||||
str += ".esm";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add plugin file (esp)
|
|
||||||
void OMW::Engine::addPlugin (const std::string& plugin)
|
|
||||||
{
|
|
||||||
mPlugins.push_back(plugin);
|
|
||||||
std::string &str = mPlugins.back();
|
|
||||||
|
|
||||||
// Append .esp if not already there
|
|
||||||
std::string::size_type sep = str.find_last_of (".");
|
|
||||||
if (sep == std::string::npos)
|
|
||||||
{
|
|
||||||
str += ".esp";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OMW::Engine::setScriptsVerbosity(bool scriptsVerbosity)
|
void OMW::Engine::setScriptsVerbosity(bool scriptsVerbosity)
|
||||||
|
@ -399,7 +379,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
mEnvironment.setWindowManager (window);
|
mEnvironment.setWindowManager (window);
|
||||||
|
|
||||||
// Create the world
|
// Create the world
|
||||||
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
|
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles,
|
||||||
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap,
|
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap,
|
||||||
mActivationDistanceOverride));
|
mActivationDistanceOverride));
|
||||||
MWBase::Environment::get().getWorld()->setupPlayer();
|
MWBase::Environment::get().getWorld()->setupPlayer();
|
||||||
|
@ -414,8 +394,8 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
|
|
||||||
//Load translation data
|
//Load translation data
|
||||||
mTranslationDataStorage.setEncoder(mEncoder);
|
mTranslationDataStorage.setEncoder(mEncoder);
|
||||||
for (size_t i = 0; i < mMaster.size(); i++)
|
for (size_t i = 0; i < mContentFiles.size(); i++)
|
||||||
mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster[i]);
|
mTranslationDataStorage.loadTranslationData(mFileCollections, mContentFiles[i]);
|
||||||
|
|
||||||
Compiler::registerExtensions (mExtensions);
|
Compiler::registerExtensions (mExtensions);
|
||||||
|
|
||||||
|
@ -480,7 +460,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
void OMW::Engine::go()
|
void OMW::Engine::go()
|
||||||
{
|
{
|
||||||
assert (!mCellName.empty());
|
assert (!mCellName.empty());
|
||||||
assert (!mMaster.empty());
|
assert (!mContentFiles.empty());
|
||||||
assert (!mOgre);
|
assert (!mOgre);
|
||||||
|
|
||||||
Settings::Manager settings;
|
Settings::Manager settings;
|
||||||
|
|
|
@ -68,8 +68,7 @@ namespace OMW
|
||||||
boost::filesystem::path mResDir;
|
boost::filesystem::path mResDir;
|
||||||
OEngine::Render::OgreRenderer *mOgre;
|
OEngine::Render::OgreRenderer *mOgre;
|
||||||
std::string mCellName;
|
std::string mCellName;
|
||||||
std::vector<std::string> mMaster;
|
std::vector<std::string> mContentFiles;
|
||||||
std::vector<std::string> mPlugins;
|
|
||||||
int mFpsLevel;
|
int mFpsLevel;
|
||||||
bool mVerboseScripts;
|
bool mVerboseScripts;
|
||||||
bool mNewGame;
|
bool mNewGame;
|
||||||
|
@ -135,13 +134,11 @@ namespace OMW
|
||||||
/// Set start cell name (only interiors for now)
|
/// Set start cell name (only interiors for now)
|
||||||
void setCell(const std::string& cellName);
|
void setCell(const std::string& cellName);
|
||||||
|
|
||||||
/// Set master file (esm)
|
/**
|
||||||
/// - If the given name does not have an extension, ".esm" is added automatically
|
* @brief addContentFile - Adds content file (ie. esm/esp, or omwgame/omwaddon) to the content files container.
|
||||||
void addMaster(const std::string& master);
|
* @param file - filename (extension is required)
|
||||||
|
*/
|
||||||
/// Same as "addMaster", but for plugin files (esp)
|
void addContentFile(const std::string& file);
|
||||||
/// - If the given name does not have an extension, ".esp" is added automatically
|
|
||||||
void addPlugin(const std::string& plugin);
|
|
||||||
|
|
||||||
/// Enable fps counter
|
/// Enable fps counter
|
||||||
void showFPS(int level);
|
void showFPS(int level);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue