summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTannin <devnull@localhost>2015-01-06 19:31:53 +0100
committerTannin <devnull@localhost>2015-01-06 19:31:53 +0100
commit9edc39633b82b5e02d33c4b0a395fe110af28eb4 (patch)
tree90d627525292cb87f3d4b7330b1847a17b568b61
parentb415db619ed027ec2acd283983624293274b090f (diff)
- bugfixes
- moved more functionality to game-plugins - further decoupled management functionality from the UI - created another "tutorial" which is only a single page with relevant parts of the ui highlighted with info as tooltips
-rw-r--r--src/dlls.manifest.debug.qt516
-rw-r--r--src/dlls.manifest.qt57
-rw-r--r--src/executableslist.cpp2
-rw-r--r--src/iuserinterface.h3
-rw-r--r--src/logbuffer.cpp8
-rw-r--r--src/main.cpp63
-rw-r--r--src/mainwindow.cpp132
-rw-r--r--src/mainwindow.h5
-rw-r--r--src/modinfo.cpp3
-rw-r--r--src/modlist.cpp4
-rw-r--r--src/motddialog.cpp2
-rw-r--r--src/organizer.pro11
-rw-r--r--src/organizercore.cpp198
-rw-r--r--src/organizercore.h18
-rw-r--r--src/organizerproxy.cpp2
-rw-r--r--src/pluginlist.h1
-rw-r--r--src/profile.cpp47
-rw-r--r--src/profile.h16
-rw-r--r--src/profilesdialog.cpp26
-rw-r--r--src/profilesdialog.h7
-rw-r--r--src/settings.cpp12
-rw-r--r--src/settings.h12
-rw-r--r--src/shared/appconfig.inc5
-rw-r--r--src/shared/fallout3info.cpp105
-rw-r--r--src/shared/fallout3info.h10
-rw-r--r--src/shared/falloutnvinfo.cpp81
-rw-r--r--src/shared/falloutnvinfo.h11
-rw-r--r--src/shared/gameinfo.cpp43
-rw-r--r--src/shared/gameinfo.h15
-rw-r--r--src/shared/oblivioninfo.cpp105
-rw-r--r--src/shared/oblivioninfo.h11
-rw-r--r--src/shared/skyriminfo.cpp109
-rw-r--r--src/shared/skyriminfo.h16
-rw-r--r--src/transfersavesdialog.cpp23
-rw-r--r--src/transfersavesdialog.h5
-rw-r--r--src/tutorials/Highlight.qml1
-rw-r--r--src/tutorials/Tooltip.qml31
-rw-r--r--src/tutorials/TooltipArea.qml55
-rw-r--r--src/tutorials/TutorialDescription.qml5
-rw-r--r--src/tutorials/TutorialOverlay.qml89
-rw-r--r--src/tutorials/tutorial_primer_main.js111
-rw-r--r--src/tutorials/tutorials.js28
42 files changed, 588 insertions, 866 deletions
diff --git a/src/dlls.manifest.debug.qt5 b/src/dlls.manifest.debug.qt5
index 1bbdf691..e49b33b8 100644
--- a/src/dlls.manifest.debug.qt5
+++ b/src/dlls.manifest.debug.qt5
@@ -1,19 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="dlls" version="1.0.0.0" processorArchitecture="x86"/>
- <file name="icuin52.dll"/>
- <file name="icuuc52.dll"/>
- <file name="icudt52.dll"/>
+ <file name="icuin53.dll"/>
+ <file name="icuuc53.dll"/>
+ <file name="icudt53.dll"/>
<file name="Qt5Cored.dll"/>
<file name="Qt5Declaratived.dll"/>
- <file name="Qt5Quickd.dll"/>
<file name="Qt5Guid.dll"/>
<file name="Qt5Multimediad.dll"/>
<file name="Qt5MultimediaWidgetsd.dll"/>
<file name="Qt5Networkd.dll"/>
<file name="Qt5OpenGLd.dll"/>
+ <file name="Qt5Positioningd.dll"/>
+ <file name="Qt5PrintSupportd.dll"/>
+ <file name="Qt5Qmld.dll"/>
+ <file name="Qt5Quickd.dll"/>
+ <file name="Qt5Sensorsd.dll"/>
<file name="Qt5Scriptd.dll"/>
<file name="Qt5Sqld.dll"/>
+ <file name="Qt5Svgd.dll"/>
+ <file name="Qt5WebChanneld.dll"/>
+ <file name="Qt5WebKitd.dll"/>
+ <file name="Qt5WebKitWidgetsd.dll"/>
<file name="Qt5Widgetsd.dll"/>
<file name="Qt5XmlPatternsd.dll"/>
</assembly>
diff --git a/src/dlls.manifest.qt5 b/src/dlls.manifest.qt5
index 59918f2b..b8f2d467 100644
--- a/src/dlls.manifest.qt5
+++ b/src/dlls.manifest.qt5
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="dlls" version="1.0.0.0" processorArchitecture="x86"/>
- <file name="icuin52.dll"/>
- <file name="icuuc52.dll"/>
- <file name="icudt52.dll"/>
+ <file name="icuin53.dll"/>
+ <file name="icuuc53.dll"/>
+ <file name="icudt53.dll"/>
<file name="Qt5Core.dll"/>
<file name="Qt5Declarative.dll"/>
<file name="Qt5Gui.dll"/>
@@ -19,6 +19,7 @@
<file name="Qt5Script.dll"/>
<file name="Qt5Sql.dll"/>
<file name="Qt5Svg.dll"/>
+ <file name="Qt5WebChannel.dll"/>
<file name="Qt5WebKit.dll"/>
<file name="Qt5WebKitWidgets.dll"/>
<file name="Qt5Widgets.dll"/>
diff --git a/src/executableslist.cpp b/src/executableslist.cpp
index 25b6bb0f..65a2ea80 100644
--- a/src/executableslist.cpp
+++ b/src/executableslist.cpp
@@ -92,7 +92,6 @@ void ExecutablesList::getExecutables(std::vector<Executable>::iterator &begin, s
end = m_Executables.end();
}
-
void ExecutablesList::getExecutables(std::vector<Executable>::const_iterator &begin,
std::vector<Executable>::const_iterator &end) const
{
@@ -100,7 +99,6 @@ void ExecutablesList::getExecutables(std::vector<Executable>::const_iterator &be
end = m_Executables.end();
}
-
const Executable &ExecutablesList::find(const QString &title) const
{
for (std::vector<Executable>::const_iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) {
diff --git a/src/iuserinterface.h b/src/iuserinterface.h
index 4799b934..ff683bce 100644
--- a/src/iuserinterface.h
+++ b/src/iuserinterface.h
@@ -20,6 +20,9 @@ public:
virtual void disconnectPlugins() = 0;
+ virtual bool closeWindow() = 0;
+ virtual void setWindowEnabled(bool enabled) = 0;
+
virtual void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab) = 0;
virtual void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives) = 0;
diff --git a/src/logbuffer.cpp b/src/logbuffer.cpp
index 635ce13e..fdfce6c5 100644
--- a/src/logbuffer.cpp
+++ b/src/logbuffer.cpp
@@ -132,8 +132,12 @@ void LogBuffer::log(QtMsgType type, const QMessageLogContext &context, const QSt
if (type == QtDebugMsg) {
fprintf(stdout, "%s [%c] %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type), qPrintable(message));
} else {
- fprintf(stdout, "%s [%c] (%s:%u) %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type),
- context.file, context.line, qPrintable(message));
+ if (context.line != 0) {
+ fprintf(stdout, "%s [%c] (%s:%u) %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type),
+ context.file, context.line, qPrintable(message));
+ } else {
+ fprintf(stdout, "%s [%c] %s\n", qPrintable(QTime::currentTime().toString()), msgTypeID(type), qPrintable(message));
+ }
}
fflush(stdout);
}
diff --git a/src/main.cpp b/src/main.cpp
index a3ddac20..92ebf8bc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -81,20 +81,52 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
using namespace MOBase;
using namespace MOShared;
+bool createAndMakeWritable(const std::wstring &subPath)
+{
+ QString fullPath = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(subPath);
+
+ if (!QDir(fullPath).exists()) {
+ QDir().mkdir(fullPath);
+ }
+
+ QFileInfo fileInfo(fullPath);
+ if (!fileInfo.exists() || !fileInfo.isWritable()) {
+ if (QMessageBox::question(nullptr, QObject::tr("Permissions required"),
+ QObject::tr("The current user account doesn't have the required access rights to run "
+ "Mod Organizer. The neccessary changes can be made automatically (the MO directory "
+ "will be made writable for the current user account). You will be asked to run "
+ "\"helper.exe\" with administrative rights."),
+ QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Yes) {
+ if (!Helper::init(GameInfo::instance().getOrganizerDirectory())) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ // no matter which directory didn't exist/wasn't writable, the helper
+ // should have created them all so we don't have to worry this message box would appear repeatedly
+ }
+ return true;
+}
+
bool bootstrap()
{
- GameInfo &gameInfo = GameInfo::instance();
-
// remove the temporary backup directory in case we're restarting after an update
- QString moDirectory = QDir::fromNativeSeparators(ToQString(gameInfo.getOrganizerDirectory()));
- QString backupDirectory = moDirectory + "/update_backup";
+ QString backupDirectory = qApp->applicationDirPath() + "/update_backup";
if (QDir(backupDirectory).exists()) {
shellDelete(QStringList(backupDirectory));
}
// cycle logfile
- removeOldFiles(ToQString(GameInfo::instance().getLogDir()), "ModOrganizer*.log", 5, QDir::Name);
+ removeOldFiles(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::logPath()),
+ "ModOrganizer*.log", 5, QDir::Name);
+
+ createAndMakeWritable(AppConfig::profilesPath());
+ createAndMakeWritable(AppConfig::modsPath());
+ createAndMakeWritable(AppConfig::downloadPath());
+ createAndMakeWritable(AppConfig::overwritePath());
+ createAndMakeWritable(AppConfig::logPath());
// verify the hook-dll exists
QString dllName = qApp->applicationDirPath() + "/" + ToQString(AppConfig::hookDLLName());
@@ -248,6 +280,7 @@ QString determineProfile(QStringList arguments, const QSettings &settings)
}
if (selectedProfileName.isEmpty()) {
qDebug("no configured profile");
+ selectedProfileName = "Default";
} else {
qDebug("configured profile: %s", qPrintable(selectedProfileName));
}
@@ -304,6 +337,11 @@ int main(int argc, char *argv[])
, ToWString(QDir::currentPath()).c_str(), SW_SHOWNORMAL);
return 1;
}
+
+ if (!bootstrap()) { // requires gameinfo to be initialised!
+ return -1;
+ }
+
LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath())));
@@ -353,8 +391,7 @@ int main(int argc, char *argv[])
}
} // we continue for the primary instance OR if MO has been called with parameters
-
- QSettings settings(dataPath + "/ModOrganizer.ini", QSettings::IniFormat);
+ QSettings settings(dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()), QSettings::IniFormat);
OrganizerCore organizer(settings);
@@ -362,7 +399,6 @@ int main(int argc, char *argv[])
pluginContainer.loadPlugins();
QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray());
-
bool done = false;
while (!done) {
if (!GameInfo::init(ToWString(application.applicationDirPath()), ToWString(dataPath), ToWString(QDir::toNativeSeparators(gamePath)))) {
@@ -418,6 +454,10 @@ int main(int argc, char *argv[])
settings.setValue("gamePath", gamePath.toUtf8().constData());
}
+ organizer.setManagedGame(ToQString(GameInfo::instance().getGameName()));
+
+ organizer.createDefaultProfile();
+
if (pluginContainer.managedGame(ToQString(GameInfo::instance().getGameName())) == nullptr) {
reportError(QObject::tr("Plugin to handle %1 not installed").arg(ToQString(GameInfo::instance().getGameName())));
return 1;
@@ -443,9 +483,6 @@ int main(int argc, char *argv[])
organizer.updateExecutablesList(settings);
- if (!bootstrap()) { // requires gameinfo to be initialised!
- return -1;
- }
QString selectedProfileName = determineProfile(arguments, settings);
organizer.setCurrentProfile(selectedProfileName);
@@ -468,7 +505,7 @@ int main(int argc, char *argv[])
}
qDebug("initializing tutorials");
- TutorialManager::init(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getTutorialDir())).append("/"));
+ TutorialManager::init(qApp->applicationDirPath() + "/" + QString::fromStdWString(AppConfig::tutorialsPath()) + "/");
if (!application.setStyleFile(settings.value("Settings/style", "").toString())) {
// disable invalid stylesheet
@@ -485,8 +522,6 @@ int main(int argc, char *argv[])
mainWindow.readSettings();
- mainWindow.createFirstProfile();
-
qDebug("displaying main window");
mainWindow.show();
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index a15da6a4..594849f2 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -137,7 +137,11 @@ using namespace MOShared;
-MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, OrganizerCore &organizerCore, PluginContainer &pluginContainer, QWidget *parent)
+MainWindow::MainWindow(const QString &exeName
+ , QSettings &initSettings
+ , OrganizerCore &organizerCore
+ , PluginContainer &pluginContainer
+ , QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_Tutorial(this, "MainWindow")
@@ -157,7 +161,6 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, Organize
{
ui->setupUi(this);
this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_OrganizerCore.getVersion().displayString());
-
languageChange(m_OrganizerCore.settings().language());
ui->logList->setModel(LogBuffer::instance());
@@ -280,6 +283,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, Organize
connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
connect(&TutorialManager::instance(), SIGNAL(windowTutorialFinished(QString)), this, SLOT(windowTutorialFinished(QString)));
+ connect(ui->tabWidget, SIGNAL(currentChanged(int)), &TutorialManager::instance(), SIGNAL(tabChanged(int)));
connect(ui->modList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(modListSortIndicatorChanged(int,Qt::SortOrder)));
connect(ui->toolBar, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(toolBar_customContextMenuRequested(QPoint)));
@@ -313,7 +317,6 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, Organize
::SetDllDirectoryW(ToWString(QDir::toNativeSeparators(qApp->applicationDirPath() + "/dlls")).c_str());
m_OrganizerCore.setUserInterface(this, this);
-
for (const QString &fileName : m_PluginContainer.pluginFileNames()) {
installTranslator(QFileInfo(fileName).baseName());
}
@@ -326,6 +329,9 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, Organize
registerModPage(modPagePlugin);
}
+ // refresh profiles so the current profile can be activated
+ refreshProfiles(false);
+
ui->profileBox->setCurrentText(m_OrganizerCore.currentProfile()->getName());
refreshExecutablesList();
@@ -477,7 +483,6 @@ void MainWindow::actionToToolButton(QAction *&sourceAction)
sourceAction = newAction;
}
-
void MainWindow::updateToolBar()
{
foreach (QAction *action, ui->toolBar->actions()) {
@@ -560,7 +565,7 @@ void MainWindow::updateProblemsButton()
bool MainWindow::errorReported(QString &logFile)
{
- QDir dir(ToQString(GameInfo::instance().getLogDir()));
+ QDir dir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::logPath()));
QFileInfoList files = dir.entryInfoList(QStringList("ModOrganizer_??_??_??_??_??.log"),
QDir::Files, QDir::Name | QDir::Reversed);
@@ -655,7 +660,7 @@ void MainWindow::createHelpWidget()
}
std::sort(tutorials.begin(), tutorials.end(),
- [](const ActionList::value_type &LHS, const ActionList::value_type &RHS) {
+ [] (const ActionList::value_type &LHS, const ActionList::value_type &RHS) {
return LHS.first < RHS.first; } );
for (auto iter = tutorials.begin(); iter != tutorials.end(); ++iter) {
@@ -816,16 +821,6 @@ void MainWindow::closeEvent(QCloseEvent* event)
}
-void MainWindow::createFirstProfile()
-{
- if (!refreshProfiles(false)) {
- qDebug("creating default profile");
- Profile newProf("Default", false);
- refreshProfiles(false);
- }
-}
-
-
void MainWindow::setBrowserGeometry(const QByteArray &geometry)
{
m_IntegratedBrowser.restoreGeometry(geometry);
@@ -1033,9 +1028,9 @@ void MainWindow::on_profileBox_currentIndexChanged(int index)
}
if (ui->profileBox->currentIndex() == 0) {
- ProfilesDialog(m_GamePath).exec();
+ ProfilesDialog(m_GamePath, m_OrganizerCore.managedGame(), this).exec();
while (!refreshProfiles()) {
- ProfilesDialog(m_GamePath).exec();
+ ProfilesDialog(m_GamePath, m_OrganizerCore.managedGame(), this).exec();
}
ui->profileBox->setCurrentIndex(previousIndex);
} else {
@@ -1181,21 +1176,15 @@ bool MainWindow::refreshProfiles(bool selectProfile)
profileBox->clear();
profileBox->addItem(QObject::tr("<Manage...>"));
- QDir profilesDir(ToQString(GameInfo::instance().getProfilesDir()));
+ QDir profilesDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()));
profilesDir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
QDirIterator profileIter(profilesDir);
- int newIndex = profileIter.hasNext() ? 1 : 0;
- int currentIndex = 0;
while (profileIter.hasNext()) {
profileIter.next();
- ++currentIndex;
try {
profileBox->addItem(profileIter.fileName());
- if (currentProfileName == profileIter.fileName()) {
- newIndex = currentIndex;
- }
} catch (const std::runtime_error& error) {
reportError(QObject::tr("failed to parse profile %1: %2").arg(profileIter.fileName()).arg(error.what()));
}
@@ -1206,20 +1195,13 @@ bool MainWindow::refreshProfiles(bool selectProfile)
if (selectProfile) {
if (profileBox->count() > 1) {
- if (currentProfileName.length() != 0) {
- if ((newIndex != 0) && (profileBox->count() > newIndex)) {
- profileBox->setCurrentIndex(newIndex);
- } else {
- profileBox->setCurrentIndex(1);
- }
+ profileBox->setCurrentText(currentProfileName);
+ if (profileBox->currentIndex() == 0) {
+ profileBox->setCurrentIndex(1);
}
- return true;
- } else {
- return false;
}
- } else {
- return profileBox->count() > 1;
}
+ return profileBox->count() > 1;
}
@@ -1301,7 +1283,7 @@ void MainWindow::refreshSaveList()
::GetPrivateProfileStringW(L"General", L"SLocalSavePath", L"Saves",
path, MAX_PATH,
(ToWString(m_OrganizerCore.currentProfile()->getPath()) + L"\\" + GameInfo::instance().getIniFileNames().at(0)).c_str());
- savesDir.setPath(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getDocumentsDir() + L"\\" + path)));
+ savesDir.setPath(m_OrganizerCore.managedGame()->documentsDirectory().absoluteFilePath(QString::fromWCharArray(path)));
}
if (m_SavesWatcher.directories().length() > 0) {
@@ -1310,11 +1292,10 @@ void MainWindow::refreshSaveList()
m_SavesWatcher.addPath(savesDir.absolutePath());
QStringList filters;
- filters << ToQString(GameInfo::instance().getSaveGameExtension());
+ filters << QString("*.") + m_OrganizerCore.managedGame()->savegameExtension();
savesDir.setNameFilters(filters);
QFileInfoList files = savesDir.entryInfoList(QDir::Files, QDir::Time);
-
foreach (const QFileInfo &file, files) {
QListWidgetItem *item = new QListWidgetItem(file.fileName());
item->setData(Qt::UserRole, file.absoluteFilePath());
@@ -1414,14 +1395,16 @@ void MainWindow::updateBSAList(const QStringList &defaultArchives, const QString
subItem->setExpanded(true);
}
- checkBSAList(defaultArchives);
+ checkBSAList();
}
-void MainWindow::checkBSAList(const QStringList &defaultArchives)
+void MainWindow::checkBSAList()
{
ui->bsaList->blockSignals(true);
+ QStringList defaultArchives = m_OrganizerCore.defaultArchiveList();
+
bool warning = false;
for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) {
@@ -1512,7 +1495,7 @@ void MainWindow::activateProxy(bool activate)
void MainWindow::readSettings()
{
- QSettings settings(ToQString(GameInfo::instance().getIniFilename()), QSettings::IniFormat);
+ QSettings settings(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::iniFileName()), QSettings::IniFormat);
if (settings.contains("window_geometry")) {
restoreGeometry(settings.value("window_geometry").toByteArray());
@@ -1791,7 +1774,7 @@ void MainWindow::on_actionAdd_Profile_triggered()
{
bool repeat = true;
while (repeat) {
- ProfilesDialog profilesDialog(m_GamePath);
+ ProfilesDialog profilesDialog(m_GamePath, m_OrganizerCore.managedGame(), this);
profilesDialog.exec();
if (refreshProfiles() && !profilesDialog.failed()) {
repeat = false;
@@ -1975,7 +1958,7 @@ void MainWindow::modRenamed(const QString &oldName, const QString &newName)
//TODO this functionality should be in the Profile class
QString modlistName = QString("%1/%2/modlist.txt")
- .arg(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())))
+ .arg(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()))
.arg(profileName);
QFile modList(modlistName);
@@ -3176,7 +3159,7 @@ void MainWindow::fixMods_clicked()
// search in overwrite
{
- QDir overwriteDir(ToQString(GameInfo::instance().getOverwriteDir()));
+ QDir overwriteDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::overwritePath()));
QStringList esps = overwriteDir.entryList(espFilter);
foreach (const QString &esp, esps) {
std::map<QString, std::vector<QString> >::iterator iter = missingPlugins.find(esp);
@@ -3398,6 +3381,8 @@ void MainWindow::languageChange(const QString &newLanguage)
updateProblemsButton();
ui->listOptionsBtn->setMenu(modListContextMenu());
+}
+
void MainWindow::writeDataToFile(QFile &file, const QString &directory, const DirectoryEntry &directoryEntry)
{
{ // list files
@@ -3433,7 +3418,6 @@ void MainWindow::writeDataToFile(QFile &file, const QString &directory, const Di
}
}
-
void MainWindow::writeDataToFile()
{
QString fileName = QFileDialog::getSaveFileName(this);
@@ -4286,62 +4270,6 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &errorMe
}
}
}
-bool MainWindow::waitForProcessOrJob(HANDLE handle, LPDWORD exitCode)
-{
- LockedDialog *dialog = new LockedDialog(this);
- dialog->show();
- setEnabled(false);
- ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); setEnabled(true); });
-
- DWORD retLen;
- JOBOBJECT_BASIC_PROCESS_ID_LIST info;
-
- bool isJobHandle = true;
-
- ULONG lastProcessID = ULONG_MAX;
- HANDLE processHandle = handle;
-
- DWORD res = ::MsgWaitForMultipleObjects(1, &handle, false, 500, QS_KEY | QS_MOUSE);
- while ((res != WAIT_FAILED) && (res != WAIT_OBJECT_0) && !dialog->unlockClicked()) {
- if (isJobHandle) {
- if (::QueryInformationJobObject(handle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) {
- if (info.NumberOfProcessIdsInList == 0) {
- // fake signaled state
- res = WAIT_OBJECT_0;
- break;
- } else {
- // this is indeed a job handle. Figure out one of the process handles as well.
- if (lastProcessID != info.ProcessIdList[0]) {
- lastProcessID = info.ProcessIdList[0];
- if (processHandle != handle) {
- ::CloseHandle(processHandle);
- }
- processHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, lastProcessID);
- }
- }
- } else {
- // the info-object I passed only provides space for 1 process id. but since this code only cares about whether there
- // is more than one that's good enough. ERROR_MORE_DATA simply signals there are at least two processes running.
- // any other error probably means the handle is a regular process handle, probably caused by running MO in a job without
- // the right to break out.
- if (::GetLastError() != ERROR_MORE_DATA) {
- isJobHandle = false;
- }
- }
- }
-
- // keep processing events so the app doesn't appear dead
- QCoreApplication::processEvents();
-
- res = ::MsgWaitForMultipleObjects(1, &handle, false, 500, QS_KEY | QS_MOUSE);
- }
-
- if (exitCode != NULL) {
- ::GetExitCodeProcess(processHandle, exitCode);
- }
- ::CloseHandle(processHandle);
-
- return res == WAIT_OBJECT_0;
}
void MainWindow::on_bossButton_clicked()
diff --git a/src/mainwindow.h b/src/mainwindow.h
index feaedef8..52c202a7 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -39,7 +39,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <archive.h>
#include "directoryrefresher.h"
#include <imoinfo.h>
-#include <iplugingame.h>
#include "settings.h"
#include "downloadmanager.h"
#include "installationmanager.h"
@@ -98,8 +97,6 @@ public:
void setModListSorting(int index);
void setESPListSorting(int index);
- void createFirstProfile();
-
bool saveArchiveList();
void registerPluginTool(MOBase::IPluginTool *tool);
@@ -303,8 +300,6 @@ private:
OrganizerCore &m_OrganizerCore;
PluginContainer &m_PluginContainer;
- MOBase::IPluginGame *m_ActiveGame;
-
QString m_CurrentLanguage;
std::vector<QTranslator*> m_Translators;
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index 4befd232..e956377c 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -29,6 +29,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <gameinfo.h>
#include <versioninfo.h>
+#include <appconfig.h>
#include <QApplication>
@@ -1012,7 +1013,7 @@ bool ModInfoOverwrite::isEmpty() const
QString ModInfoOverwrite::absolutePath() const
{
- return QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOverwriteDir()));
+ return QDir::fromNativeSeparators(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::overwritePath()));
}
std::vector<ModInfo::EFlag> ModInfoOverwrite::getFlags() const
diff --git a/src/modlist.cpp b/src/modlist.cpp
index 6d55764a..55344865 100644
--- a/src/modlist.cpp
+++ b/src/modlist.cpp
@@ -25,6 +25,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "qtgroupingproxy.h"
#include "viewmarkingscrollbar.h"
#include <gameinfo.h>
+#include <appconfig.h>
#include <utility.h>
#include <QFileInfo>
#include <QDir>
@@ -41,6 +42,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QWidgetAction>
#include <QAbstractItemView>
#include <QSortFilterProxyModel>
+#include <QApplication>
#include <sstream>
#include <algorithm>
@@ -750,7 +752,7 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa
ModInfo::Ptr modInfo = ModInfo::getByIndex(row);
QDir modDirectory(modInfo->absolutePath());
- QDir gameDirectory(QDir::fromNativeSeparators(ToQString(MOShared::GameInfo::instance().getOverwriteDir())));
+ QDir gameDirectory(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::overwritePath()));
unsigned int overwriteIndex = ModInfo::findMod([](ModInfo::Ptr mod) -> bool {
std::vector<ModInfo::EFlag> flags = mod->getFlags();
diff --git a/src/motddialog.cpp b/src/motddialog.cpp
index 59ace4d1..96d88542 100644
--- a/src/motddialog.cpp
+++ b/src/motddialog.cpp
@@ -28,8 +28,6 @@ MotDDialog::MotDDialog(const QString &message, QWidget *parent)
{
ui->setupUi(this);
ui->motdView->setHtml(BBCode::convertToHTML(message));
-// ui->motdView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
-// connect(ui->motdView->page(), SIGNAL(linkClicked(QUrl)), this, SLOT(linkClicked(QUrl)));
connect(ui->motdView, SIGNAL(anchorClicked(QUrl)), this, SLOT(linkClicked(QUrl)));
}
diff --git a/src/organizer.pro b/src/organizer.pro
index 4524a09b..b67fb3e5 100644
--- a/src/organizer.pro
+++ b/src/organizer.pro
@@ -249,7 +249,7 @@ LIBS += -L"E:/Visual Leak Detector/lib/Win32"
#DEFINES += LEAK_CHECK_WITH_VLD
# custom leak detection
-LIBS += -lDbgHelp
+#LIBS += -lDbgHelp
# model tests
#SOURCES += modeltest.cpp
@@ -257,7 +257,7 @@ LIBS += -lDbgHelp
#DEFINES += TEST_MODELS
-INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk ../boss_modified/boss-api "$${BOOSTPATH}"
+INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk "$${LOOTPATH}" "$${BOOSTPATH}"
LIBS += -L"$${BOOSTPATH}/stage/lib"
@@ -317,7 +317,7 @@ LIBS += -L"$${ZLIBPATH}/build" -lzlibstatic
DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS NOMINMAX
-DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
+DEFINES += BOOST_DISABLE_ASSERTS NDEBUG QT_MESSAGELOGCONTEXT
#DEFINES += QMLJSDEBUGGER
HGID = $$system(hg id -i)
@@ -361,3 +361,8 @@ CONFIG(debug, debug|release) {
QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
}
}
+
+DISTFILES += \
+ tutorials/tutorial_primer_main.js \
+ tutorials/Tooltip.qml \
+ tutorials/TooltipArea.qml
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 5b322a0a..936e5529 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -77,52 +77,6 @@ static std::wstring getProcessName(DWORD processId)
}
}
-bool OrganizerCore::testForSteam()
-{
- size_t currentSize = 1024;
- std::unique_ptr<DWORD[]> processIDs;
- DWORD bytesReturned;
- bool success = false;
- while (!success) {
- processIDs.reset(new DWORD[currentSize]);
- if (!::EnumProcesses(processIDs.get(), currentSize * sizeof(DWORD), &bytesReturned)) {
- qWarning("failed to determine if steam is running");
- return true;
- }
- if (bytesReturned == (currentSize * sizeof(DWORD))) {
- // maximum size used, list probably truncated
- currentSize *= 2;
- } else {
- success = true;
- }
- }
- TCHAR processName[MAX_PATH];
- for (unsigned int i = 0; i < bytesReturned / sizeof(DWORD); ++i) {
- memset(processName, '\0', sizeof(TCHAR) * MAX_PATH);
- if (processIDs[i] != 0) {
- HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]);
-
- if (process != nullptr) {
- HMODULE module;
- DWORD ignore;
-
- // first module in a process is always the binary
- if (EnumProcessModules(process, &module, sizeof(HMODULE) * 1, &ignore)) {
- ::GetModuleBaseName(process, module, processName, MAX_PATH);
- if ((_tcsicmp(processName, TEXT("steam.exe")) == 0) ||
- (_tcsicmp(processName, TEXT("steamservice.exe")) == 0)) {
- return true;
- }
- }
- } else {
- qDebug("can't open process %lu: %lu", processIDs[i], ::GetLastError());
- }
- }
- }
-
- return false;
-}
-
static void startSteam(QWidget *widget)
{
QSettings steamSettings("HKEY_CURRENT_USER\\Software\\Valve\\Steam", QSettings::NativeFormat);
@@ -153,6 +107,7 @@ OrganizerCore::OrganizerCore(const QSettings &initSettings)
: m_GameInfo(new GameInfoImpl())
, m_UserInterface(nullptr)
, m_PluginContainer(nullptr)
+ , m_GameName()
, m_CurrentProfile(nullptr)
, m_Settings(initSettings)
, m_Updater(NexusInterface::instance())
@@ -188,6 +143,8 @@ OrganizerCore::OrganizerCore(const QSettings &initSettings)
connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool)));
connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
+ connect(this, SIGNAL(managedGameChanged(MOBase::IPluginGame*)), &m_Settings, SLOT(managedGameChanged(MOBase::IPluginGame*)));
+
// make directory refresher run in a separate thread
m_RefresherThread.start();
m_DirectoryRefresher.moveToThread(&m_RefresherThread);
@@ -217,7 +174,7 @@ OrganizerCore::~OrganizerCore()
void OrganizerCore::storeSettings()
{
- QString iniFile = ToQString(GameInfo::instance().getIniFilename());
+ QString iniFile = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::iniFileName());
shellCopy(iniFile, iniFile + ".new", true, qApp->activeWindow());
QSettings::Status result = QSettings::NoError;
@@ -275,8 +232,57 @@ void OrganizerCore::storeSettings()
}
}
+bool OrganizerCore::testForSteam()
+{
+ size_t currentSize = 1024;
+ std::unique_ptr<DWORD[]> processIDs;
+ DWORD bytesReturned;
+ bool success = false;
+ while (!success) {
+ processIDs.reset(new DWORD[currentSize]);
+ if (!::EnumProcesses(processIDs.get(), currentSize * sizeof(DWORD), &bytesReturned)) {
+ qWarning("failed to determine if steam is running");
+ return true;
+ }
+ if (bytesReturned == (currentSize * sizeof(DWORD))) {
+ // maximum size used, list probably truncated
+ currentSize *= 2;
+ } else {
+ success = true;
+ }
+ }
+ TCHAR processName[MAX_PATH];
+ for (unsigned int i = 0; i < bytesReturned / sizeof(DWORD); ++i) {
+ memset(processName, '\0', sizeof(TCHAR) * MAX_PATH);
+ if (processIDs[i] != 0) {
+ HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]);
+
+ if (process != nullptr) {
+ HMODULE module;
+ DWORD ignore;
+
+ // first module in a process is always the binary
+ if (EnumProcessModules(process, &module, sizeof(HMODULE) * 1, &ignore)) {
+ ::GetModuleBaseName(process, module, processName, MAX_PATH);
+ if ((_tcsicmp(processName, TEXT("steam.exe")) == 0) ||
+ (_tcsicmp(processName, TEXT("steamservice.exe")) == 0)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
void OrganizerCore::updateExecutablesList(QSettings &settings)
{
+ if (m_PluginContainer == nullptr) {
+ qCritical("can't update executables list now");
+ return;
+ }
+
m_ExecutablesList.init(m_PluginContainer->managedGame(ToQString(GameInfo::instance().getGameName())));
qDebug("setting up configured executables");
@@ -337,6 +343,11 @@ void OrganizerCore::connectPlugins(PluginContainer *container)
{
m_DownloadManager.setSupportedExtensions(m_InstallationManager.getSupportedExtensions());
m_PluginContainer = container;
+
+ if (!m_GameName.isEmpty()) {
+ m_GamePlugin = m_PluginContainer->managedGame(m_GameName);
+ emit managedGameChanged(m_GamePlugin);
+ }
}
void OrganizerCore::disconnectPlugins()
@@ -348,9 +359,19 @@ void OrganizerCore::disconnectPlugins()
m_PluginList.disconnectSlots();
m_Settings.clearPlugins();
+ m_GamePlugin = nullptr;
m_PluginContainer = nullptr;
}
+void OrganizerCore::setManagedGame(const QString &gameName)
+{
+ m_GameName = gameName;
+ if (m_PluginContainer != nullptr) {
+ m_GamePlugin = m_PluginContainer->managedGame(m_GameName);
+ emit managedGameChanged(m_GamePlugin);
+ }
+}
+
Settings &OrganizerCore::settings()
{
return m_Settings;
@@ -449,11 +470,19 @@ InstallationManager *OrganizerCore::installationManager()
return &m_InstallationManager;
}
+void OrganizerCore::createDefaultProfile()
+{
+ QString profilesPath = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath());
+ qDebug("%d", QDir(profilesPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot).size());
+ if (QDir(profilesPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot).size() == 0) {
+ Profile newProf("Default", managedGame(), false);
+ }
+}
+
void OrganizerCore::setCurrentProfile(const QString &profileName)
{
QString profileDir = qApp->property("dataPath").toString() + "/" + ToQString(AppConfig::profilesPath()) + "/" + profileName;
-
- Profile *newProfile = new Profile(QDir(profileDir));
+ Profile *newProfile = new Profile(QDir(profileDir), managedGame());
delete m_CurrentProfile;
m_CurrentProfile = newProfile;
@@ -576,8 +605,7 @@ void OrganizerCore::setPersistent(const QString &pluginName, const QString &key,
QString OrganizerCore::pluginDataPath() const
{
- QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
- return pluginPath + "/data";
+ return qApp->applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()) + "/data";
}
MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName, const QString &initModName)
@@ -676,63 +704,6 @@ void OrganizerCore::installDownload(int index)
}
}
-void OrganizerCore::installDownload(int downloadIndex)
-{
- try {
- QString fileName = m_DownloadManager.getFilePath(downloadIndex);
- int modID = m_DownloadManager.getModID(downloadIndex);
- GuessedValue<QString> modName;
-
- // see if there already are mods with the specified mod id
- if (modID != 0) {
- std::vector<ModInfo::Ptr> modInfo = ModInfo::getByModID(modID);
- for (auto iter = modInfo.begin(); iter != modInfo.end(); ++iter) {
- std::vector<ModInfo::EFlag> flags = (*iter)->getFlags();
- if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) == flags.end()) {
- modName.update((*iter)->name(), GUESS_PRESET);
- (*iter)->saveMeta();
- }
- }
- }
-
- m_CurrentProfile->writeModlistNow();
-
- bool hasIniTweaks = false;
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
- if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) {
- MessageDialog::showMessage(tr("Installation successful"), qApp->activeWindow());
- refreshModList();
-
- int modIndex = ModInfo::getIndex(modName);
- if (modIndex != UINT_MAX) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
-
- if (hasIniTweaks
- && (m_UserInterface != nullptr)
- && (QMessageBox::question(qApp->activeWindow(), tr("Configure Mod"),
- tr("This mod contains ini tweaks. Do you want to configure them now?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) {
- m_UserInterface->displayModInformation(modInfo, modIndex, ModInfoDialog::TAB_INIFILES);
- }
-
- m_ModInstalled(modName);
- } else {
- reportError(tr("mod \"%1\" not found").arg(modName));
- }
- m_DownloadManager.markInstalled(downloadIndex);
-
- emit modInstalled(modName);
- } else if (m_InstallationManager.wasCancelled()) {
- QMessageBox::information(qApp->activeWindow(),
- tr("Installation cancelled"),
- tr("The mod was not installed completely."),
- QMessageBox::Ok);
- }
- } catch (const std::exception &e) {
- reportError(e.what());
- }
-}
-
QString OrganizerCore::resolvePath(const QString &fileName) const
{
if (m_DirectoryStructure == nullptr) {
@@ -1011,7 +982,7 @@ HANDLE OrganizerCore::startApplication(const QString &executable, const QStringL
return spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID);
}
-bool OrganizerCore::waitForProcessOrJob(HANDLE handle, LPDWORD exitCode)
+bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode)
{
if (m_UserInterface != nullptr) {
m_UserInterface->lock();
@@ -1131,7 +1102,7 @@ QStringList OrganizerCore::defaultArchiveList()
result.append(ToQString(buffer).split(','));
}
- for (int i = 0; i < m_DefaultArchives.count(); ++i) {
+ for (int i = 0; i < result.count(); ++i) {
result[i] = result[i].trimmed();
}
@@ -1284,6 +1255,11 @@ PluginListSortProxy *OrganizerCore::createPluginListProxyModel()
return result;
}
+IPluginGame *OrganizerCore::managedGame() const
+{
+ return m_GamePlugin;
+}
+
std::set<QString> OrganizerCore::enabledArchives()
{
std::set<QString> result;
@@ -1308,8 +1284,6 @@ void OrganizerCore::refreshDirectoryStructure()
m_DirectoryRefresher.setMods(activeModList, enabledArchives());
QTimer::singleShot(0, &m_DirectoryRefresher, SLOT(refresh()));
- } else {
- qDebug("directory update");
}
}
diff --git a/src/organizercore.h b/src/organizercore.h
index cf8d10f5..4d9b0a7c 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -17,6 +17,7 @@
#include <directoryentry.h>
#include <imoinfo.h>
#include <iplugindiagnose.h>
+#include <iplugingame.h>
#include <versioninfo.h>
#include <guessedvalue.h>
#include <boost/signals2.hpp>
@@ -27,6 +28,9 @@
class PluginContainer;
+namespace MOBase {
+ class IPluginGame;
+}
class OrganizerCore : public QObject, public MOBase::IPluginDiagnose
{
@@ -68,6 +72,8 @@ public:
void connectPlugins(PluginContainer *container);
void disconnectPlugins();
+ void setManagedGame(const QString &gameName);
+
void updateExecutablesList(QSettings &settings);
void startMOUpdate();
@@ -92,7 +98,7 @@ public:
ModListSortProxy *createModListProxyModel();
PluginListSortProxy *createPluginListProxyModel();
- HANDLE spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, const QDir &currentDirectory, const QString &steamAppID);
+ MOBase::IPluginGame *managedGame() const;
bool isArchivesInit() const { return m_ArchivesInit; }
@@ -116,6 +122,8 @@ public:
void syncOverwrite();
+ void createDefaultProfile();
+
public:
MOBase::IGameInfo &gameInfo() const;
MOBase::IModRepositoryBridge *createNexusBridge() const;
@@ -132,7 +140,7 @@ public:
QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def) const;
void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync);
QString pluginDataPath() const;
- virtual MOBase::IModInterface *installMod(const QString &fileName);
+ virtual MOBase::IModInterface *installMod(const QString &fileName, const QString &initModName);
QString resolvePath(const QString &fileName) const;
QStringList listDirectories(const QString &directoryName) const;
QStringList findFiles(const QString &path, const std::function<bool (const QString &)> &filter) const;
@@ -147,6 +155,7 @@ public:
bool onAboutToRun(const std::function<bool (const QString &)> &func);
bool onFinishedRun(const std::function<void (const QString &, unsigned int)> &func);
void refreshModList(bool saveChanges = true);
+ QStringList defaultArchiveList();
public: // IPluginDiagnose interface
@@ -181,6 +190,8 @@ signals:
*/
void modInstalled(const QString &modName);
+ void managedGameChanged(MOBase::IPluginGame *gamePlugin);
+
private:
void storeSettings();
@@ -190,7 +201,6 @@ private:
void updateModActiveState(int index, bool active);
bool testForSteam();
- QStringList defaultArchiveList();
private slots:
@@ -211,6 +221,8 @@ private:
IUserInterface *m_UserInterface;
PluginContainer *m_PluginContainer;
+ QString m_GameName;
+ MOBase::IPluginGame *m_GamePlugin;
Profile *m_CurrentProfile;
diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp
index ff030d40..2ce5b3ee 100644
--- a/src/organizerproxy.cpp
+++ b/src/organizerproxy.cpp
@@ -102,7 +102,7 @@ HANDLE OrganizerProxy::startApplication(const QString &executable, const QString
bool OrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const
{
- return m_Proxied->waitForProcessOrJob(handle, exitCode);
+ return m_Proxied->waitForApplication(handle, exitCode);
}
bool OrganizerProxy::onAboutToRun(const std::function<bool (const QString &)> &func)
diff --git a/src/pluginlist.h b/src/pluginlist.h
index da644ad3..e0913840 100644
--- a/src/pluginlist.h
+++ b/src/pluginlist.h
@@ -33,7 +33,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <vector>
#include <map>
#include "pdll.h"
-#include <BOSS-API.h>
template <class C>
diff --git a/src/profile.cpp b/src/profile.cpp
index 21c9d1d8..775b309e 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -28,6 +28,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <util.h>
#include <error_report.h>
#include <appconfig.h>
+#include <iplugingame.h>
#include <QMessageBox>
#include <QApplication>
#include <QSettings>
@@ -55,12 +56,11 @@ void Profile::touchFile(QString fileName)
}
}
-Profile::Profile(const QString &name, bool useDefaultSettings)
+Profile::Profile(const QString &name, IPluginGame *gamePlugin, bool useDefaultSettings)
: m_SaveTimer(nullptr)
{
initTimer();
- QString profilesDir = qApp->property("datapath").toString() + "/" + ToQString(AppConfig::profilesPath());
-qDebug("pd %s", qPrintable(profilesDir));
+ QString profilesDir = qApp->property("dataPath").toString() + "/" + ToQString(AppConfig::profilesPath());
QDir profileBase(profilesDir);
QString fixedName = name;
@@ -79,8 +79,15 @@ qDebug("pd %s", qPrintable(profilesDir));
touchFile("modlist.txt");
touchFile("archives.txt");
-qDebug("fp %s", qPrintable(fullPath));
- GameInfo::instance().createProfile(ToWString(fullPath), useDefaultSettings);
+ IPluginGame::ProfileSettings settings = IPluginGame::CONFIGURATION
+ | IPluginGame::MODS
+ | IPluginGame::SAVEGAMES;
+
+ if (useDefaultSettings) {
+ settings |= IPluginGame::PREFER_DEFAULTS;
+ }
+
+ gamePlugin->initializeProfile(fullPath, settings);
} catch (...) {
// clean up in case of an error
shellDelete(QStringList(profileBase.absoluteFilePath(fixedName)));
@@ -90,15 +97,21 @@ qDebug("fp %s", qPrintable(fullPath));
}
-Profile::Profile(const QDir &directory)
+Profile::Profile(const QDir &directory, IPluginGame *gamePlugin)
: m_Directory(directory), m_SaveTimer(nullptr)
{
+ assert(gamePlugin != nullptr);
initTimer();
+
if (!QFile::exists(m_Directory.filePath("modlist.txt"))) {
qWarning("missing modlist.txt in %s", qPrintable(directory.path()));
+ touchFile(m_Directory.filePath("modlist.txt"));
}
- GameInfo::instance().repairProfile(ToWString(m_Directory.absolutePath()));
+ IPluginGame::ProfileSettings settings = IPluginGame::CONFIGURATION
+ | IPluginGame::MODS
+ | IPluginGame::SAVEGAMES;
+ gamePlugin->initializeProfile(directory, settings);
if (!QFile::exists(getIniFileName())) {
reportError(QObject::tr("\"%1\" is missing or inaccessible").arg(getIniFileName()));
@@ -492,29 +505,18 @@ void Profile::setModPriority(unsigned int index, int &newPriority)
writeModlist();
}
-
-Profile Profile::createFrom(const QString &name, const Profile &reference)
+Profile *Profile::createPtrFrom(const QString &name, const Profile &reference, MOBase::IPluginGame *gamePlugin)
{
- QString profileDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())).append("/").append(name);
+ QString profileDirectory = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()) + "/" + name;
reference.copyFilesTo(profileDirectory);
- return Profile(QDir(profileDirectory));
+ return new Profile(QDir(profileDirectory), gamePlugin);
}
-
-Profile *Profile::createPtrFrom(const QString &name, const Profile &reference)
-{
- QString profileDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())).append("/").append(name);
- reference.copyFilesTo(profileDirectory);
- return new Profile(QDir(profileDirectory));
-}
-
-
void Profile::copyFilesTo(QString &target) const
{
copyDir(m_Directory.absolutePath(), target, false);
}
-
std::vector<std::wstring> Profile::splitDZString(const wchar_t *buffer) const
{
std::vector<std::wstring> result;
@@ -528,7 +530,6 @@ std::vector<std::wstring> Profile::splitDZString(const wchar_t *buffer) const
return result;
}
-
void Profile::mergeTweak(const QString &tweakName, const QString &tweakedIni) const
{
static const int bufferSize = 32768;
@@ -787,7 +788,7 @@ QString Profile::getPath() const
void Profile::rename(const QString &newName)
{
- QDir profileDir(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())));
+ QDir profileDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()));
profileDir.rename(getName(), newName);
m_Directory = profileDir.absoluteFilePath(newName);
}
diff --git a/src/profile.h b/src/profile.h
index aa27d6e8..34efd4b2 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -31,6 +31,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <tuple>
+namespace MOBase {
+ class IPluginGame;
+}
+
/**
* @brief represents a profile
**/
@@ -59,7 +63,7 @@ public:
* @param name name of the new profile
* @param filter save game filter. Defaults to &lt;no filter&gt;.
**/
- Profile(const QString &name, bool useDefaultSettings);
+ Profile(const QString &name, MOBase::IPluginGame *gamePlugin, bool useDefaultSettings);
/**
* @brief constructor
*
@@ -68,7 +72,7 @@ public:
* invoking this should always produce a working profile
* @param directory directory to read the profile from
**/
- Profile(const QDir &directory);
+ Profile(const QDir &directory, MOBase::IPluginGame *gamePlugin);
Profile(const Profile &reference);
@@ -83,13 +87,7 @@ public:
* @param name of the new profile
* @param reference profile to copy from
**/
- static Profile createFrom(const QString &name, const Profile &reference);
-
- /**
- * @param name of the new profile
- * @param reference profile to copy from
- **/
- static Profile *createPtrFrom(const QString &name, const Profile &reference);
+ static Profile *createPtrFrom(const QString &name, const Profile &reference, MOBase::IPluginGame *gamePlugin);
/**
* @brief write out the modlist.txt
diff --git a/src/profilesdialog.cpp b/src/profilesdialog.cpp
index 26891b3c..02566db3 100644
--- a/src/profilesdialog.cpp
+++ b/src/profilesdialog.cpp
@@ -26,6 +26,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "profileinputdialog.h"
#include "mainwindow.h"
#include <gameinfo.h>
+#include <appconfig.h>
#include <QListWidgetItem>
#include <QInputDialog>
#include <QLineEdit>
@@ -40,12 +41,16 @@ using namespace MOShared;
Q_DECLARE_METATYPE(Profile::Ptr)
-ProfilesDialog::ProfilesDialog(const QString &gamePath, QWidget *parent)
- : TutorableDialog("Profiles", parent), ui(new Ui::ProfilesDialog), m_GamePath(gamePath), m_FailState(false)
+ProfilesDialog::ProfilesDialog(const QString &gamePath, MOBase::IPluginGame *gamePlugin, QWidget *parent)
+ : TutorableDialog("Profiles", parent)
+ , ui(new Ui::ProfilesDialog)
+ , m_GamePlugin(gamePlugin)
+ , m_GamePath(gamePath)
+ , m_FailState(false)
{
ui->setupUi(this);
- QDir profilesDir(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())));
+ QDir profilesDir(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::profilesPath()));
profilesDir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
m_ProfilesList = findChild<QListWidget*>("profilesList");
@@ -93,20 +98,19 @@ void ProfilesDialog::addItem(const QString &name)
QDir profileDir(name);
QListWidgetItem *newItem = new QListWidgetItem(profileDir.dirName(), m_ProfilesList);
try {
- newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(profileDir))));
+ newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(profileDir, m_GamePlugin))));
m_FailState = false;
} catch (const std::exception& e) {
reportError(tr("failed to create profile: %1").arg(e.what()));
}
}
-
void ProfilesDialog::createProfile(const QString &name, bool useDefaultSettings)
{
try {
QListWidget *profilesList = findChild<QListWidget*>("profilesList");
QListWidgetItem *newItem = new QListWidgetItem(name, profilesList);
- newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(name, useDefaultSettings))));
+ newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(new Profile(name, m_GamePlugin, useDefaultSettings))));
profilesList->addItem(newItem);
m_FailState = false;
} catch (const std::exception&) {
@@ -115,13 +119,12 @@ void ProfilesDialog::createProfile(const QString &name, bool useDefaultSettings)
}
}
-
void ProfilesDialog::createProfile(const QString &name, const Profile &reference)
{
try {
QListWidget *profilesList = findChild<QListWidget*>("profilesList");
QListWidgetItem *newItem = new QListWidgetItem(name, profilesList);
- newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(Profile::createPtrFrom(name, reference))));
+ newItem->setData(Qt::UserRole, QVariant::fromValue(Profile::Ptr(Profile::createPtrFrom(name, reference, m_GamePlugin))));
profilesList->addItem(newItem);
m_FailState = false;
} catch (const std::exception&) {
@@ -130,7 +133,6 @@ void ProfilesDialog::createProfile(const QString &name, const Profile &reference
}
}
-
void ProfilesDialog::on_addProfileButton_clicked()
{
ProfileInputDialog dialog(this);
@@ -178,7 +180,9 @@ void ProfilesDialog::on_removeProfileButton_clicked()
Profile::Ptr currentProfile = profilesList->currentItem()->data(Qt::UserRole).value<Profile::Ptr>();
QString profilePath;
if (currentProfile.get() == nullptr) {
- profilePath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())) + "/" + profilesList->currentItem()->text();
+ profilePath = qApp->property("dataPath").toString()
+ + "/" + QString::fromStdWString(AppConfig::profilesPath())
+ + "/" + profilesList->currentItem()->text();
if (QMessageBox::question(this, tr("Profile broken"),
tr("This profile you're about to delete seems to be broken or the path is invalid. "
"I'm about to delete the following folder: \"%1\". Proceed?").arg(profilePath), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
@@ -315,6 +319,6 @@ void ProfilesDialog::on_localSavesBox_stateChanged(int state)
void ProfilesDialog::on_transferButton_clicked()
{
const Profile::Ptr currentProfile = m_ProfilesList->currentItem()->data(Qt::UserRole).value<Profile::Ptr>();
- TransferSavesDialog transferDialog(*currentProfile, this);
+ TransferSavesDialog transferDialog(*currentProfile, m_GamePlugin, this);
transferDialog.exec();
}
diff --git a/src/profilesdialog.h b/src/profilesdialog.h
index 905d49b1..18b3932f 100644
--- a/src/profilesdialog.h
+++ b/src/profilesdialog.h
@@ -29,6 +29,10 @@ namespace Ui {
class ProfilesDialog;
}
+namespace MOBase {
+ class IPluginGame;
+}
+
/**
* @brief Dialog that can be used to create/delete/modify profiles
@@ -46,7 +50,7 @@ public:
* @param parent parent widget
* @todo the game path could be retrieved from GameInfo just as easily
**/
- explicit ProfilesDialog(const QString &gamePath, QWidget *parent = 0);
+ explicit ProfilesDialog(const QString &gamePath, MOBase::IPluginGame *gamePlugin, QWidget *parent = 0);
~ProfilesDialog();
/**
@@ -87,6 +91,7 @@ private slots:
private:
Ui::ProfilesDialog *ui;
+ MOBase::IPluginGame *m_GamePlugin;
QString m_GamePath;
QListWidget *m_ProfilesList;
bool m_FailState;
diff --git a/src/settings.cpp b/src/settings.cpp
index f44edb24..a052620d 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -22,10 +22,11 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "settingsdialog.h"
#include "utility.h"
#include "helper.h"
+#include "json.h"
#include <gameinfo.h>
#include <appconfig.h>
#include <utility.h>
-#include "json.h"
+#include <iplugingame.h>
#include <QCheckBox>
#include <QLineEdit>
@@ -117,6 +118,11 @@ void Settings::registerAsNXMHandler(bool force)
}
}
+void Settings::managedGameChanged(IPluginGame *gamePlugin)
+{
+ m_GamePlugin = gamePlugin;
+}
+
void Settings::registerPlugin(IPlugin *plugin)
{
m_Plugins.push_back(plugin);
@@ -176,7 +182,7 @@ bool Settings::automaticLoginEnabled() const
QString Settings::getSteamAppID() const
{
- return m_Settings.value("Settings/app_id", ToQString(GameInfo::instance().getSteamAPPId(m_Settings.value("game_edition", 0).toInt()))).toString();
+ return m_Settings.value("Settings/app_id", m_GamePlugin->steamAPPId()).toString();
}
QString Settings::getDownloadDirectory() const
@@ -691,7 +697,7 @@ void Settings::query(QWidget *parent)
m_Settings.setValue("Settings/log_level", logLevelBox->currentIndex());
- if (appIDEdit->text() != ToQString(GameInfo::instance().getSteamAPPId())) {
+ if (appIDEdit->text() != m_GamePlugin->steamAPPId()) {
m_Settings.setValue("Settings/app_id", appIDEdit->text());
} else {
m_Settings.remove("Settings/app_id");
diff --git a/src/settings.h b/src/settings.h
index cea4729a..51e109c4 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -29,6 +29,11 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QComboBox>
+namespace MOBase {
+ class IPluginGame;
+}
+
+
/**
* manages the settings for Mod Organizer. The settings are not cached
* inside the class but read/written directly from/to disc
@@ -272,6 +277,11 @@ public:
* even if the user said earlier not to
*/
void registerAsNXMHandler(bool force);
+
+public slots:
+
+ void managedGameChanged(MOBase::IPluginGame *gamePlugin);
+
private:
QString obfuscate(const QString &password) const;
@@ -296,6 +306,8 @@ private:
static Settings *s_Instance;
+ MOBase::IPluginGame *m_GamePlugin;
+
QSettings m_Settings;
LoadMechanism m_LoadMechanism;
diff --git a/src/shared/appconfig.inc b/src/shared/appconfig.inc
index 4450763f..e2dbfe20 100644
--- a/src/shared/appconfig.inc
+++ b/src/shared/appconfig.inc
@@ -6,8 +6,11 @@ APPPARAM(std::wstring, downloadPath, L"downloads")
APPPARAM(std::wstring, overwritePath, L"overwrite")
APPPARAM(std::wstring, stylesheetsPath, L"stylesheets")
APPPARAM(std::wstring, cachePath, L"webcache")
+APPPARAM(std::wstring, tutorialsPath, L"tutorials")
+APPPARAM(std::wstring, logPath, L"logs")
APPPARAM(std::wstring, profileTweakIni, L"profile_tweaks.ini")
-APPPARAM(std::wstring, logFile, L"ModOrganizer.log")
+APPPARAM(std::wstring, logFileName, L"ModOrganizer.log")
+APPPARAM(std::wstring, iniFileName, L"ModOrganizer.ini")
APPPARAM(std::wstring, proxyDLLTarget, L"steam_api.dll")
APPPARAM(std::wstring, proxyDLLOrig, L"steam_api_orig.dll") // needs to be identical to the value used in proxydll-project
APPPARAM(std::wstring, proxyDLLSource, L"proxy.dll")
diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp
index 6c420044..c8688cc4 100644
--- a/src/shared/fallout3info.cpp
+++ b/src/shared/fallout3info.cpp
@@ -84,21 +84,6 @@ bool Fallout3Info::isInvalidationBSA(const std::wstring &bsaName)
return false;
}
-std::wstring Fallout3Info::getDocumentsDir()
-{
- std::wostringstream temp;
- temp << getMyGamesDirectory() << L"\\Fallout3";
-
- return temp.str();
-}
-
-std::wstring Fallout3Info::getSaveGameDir()
-{
- std::wostringstream temp;
- temp << getDocumentsDir() << L"\\Saves";
- return temp.str();
-}
-
std::vector<std::wstring> Fallout3Info::getPrimaryPlugins()
{
return boost::assign::list_of(L"fallout3.esm");
@@ -134,11 +119,6 @@ std::vector<std::wstring> Fallout3Info::getIniFileNames()
return boost::assign::list_of(L"fallout.ini")(L"falloutprefs.ini");
}
-std::wstring Fallout3Info::getSaveGameExtension()
-{
- return L"*.fos";
-}
-
std::wstring Fallout3Info::getReferenceDataFile()
{
return L"Fallout - Meshes.bsa";
@@ -155,21 +135,11 @@ std::vector<std::wstring> Fallout3Info::getSteamVariants() const
return boost::assign::list_of(L"Regular")(L"Game Of The Year");
}
-std::wstring Fallout3Info::getSteamAPPId(int variant) const
-{
- switch (variant) {
- case 1: return L"22370";
- default: return L"22300";
- }
-}
-
-
std::wstring Fallout3Info::getSEName()
{
return L"fose";
}
-
std::wstring Fallout3Info::getNexusPage(bool nmmScheme)
{
if (nmmScheme) {
@@ -192,68 +162,6 @@ int Fallout3Info::getNexusModIDStatic()
}
-void Fallout3Info::createProfile(const std::wstring &directory, bool useDefaults)
-{
- std::wostringstream target;
-
- // copy plugins.txt
- target << directory << "\\plugins.txt";
-
- if (!FileExists(target.str())) {
- std::wostringstream source;
- source << getLocalAppFolder() << "\\Fallout3\\plugins.txt";
- if (!::CopyFileW(source.str().c_str(), target.str().c_str(), true)) {
- HANDLE file = ::CreateFileW(target.str().c_str(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
- ::CloseHandle(file);
- }
- }
-
- // copy ini-file
- target.str(L""); target.clear();
- target << directory << L"\\fallout.ini";
-
- if (!FileExists(target.str())) {
- std::wostringstream source;
- if (useDefaults) {
- source << getGameDirectory() << L"\\fallout_default.ini";
- } else {
- source << getMyGamesDirectory() << L"\\Fallout3";
- if (FileExists(source.str(), L"fallout.ini")) {
- source << L"\\fallout.ini";
- } else {
- source.str(L"");
- source << getGameDirectory() << L"\\fallout_default.ini";
- }
- }
-
- if (!::CopyFileW(source.str().c_str(), target.str().c_str(), true)) {
- if (::GetLastError() != ERROR_FILE_EXISTS) {
- std::ostringstream stream;
- stream << "failed to copy ini file: " << ToString(source.str(), false);
- throw windows_error(stream.str());
- }
- }
- }
- { // copy falloutprefs.ini-file
- std::wstring target = directory + L"\\falloutprefs.ini";
- if (!FileExists(target)) {
- std::wstring source = getMyGamesDirectory() + L"\\Fallout3\\falloutprefs.ini";
- if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
- if (::GetLastError() != ERROR_FILE_EXISTS) {
- throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false));
- }
- }
- }
- }
-}
-
-
-void Fallout3Info::repairProfile(const std::wstring &directory)
-{
- createProfile(directory, false);
-}
-
-
bool Fallout3Info::rerouteToProfile(const wchar_t *fileName, const wchar_t*)
{
static LPCWSTR profileFiles[] = { L"fallout.ini", L"falloutprefs.ini", L"plugins.txt", nullptr };
@@ -266,17 +174,4 @@ bool Fallout3Info::rerouteToProfile(const wchar_t *fileName, const wchar_t*)
return false;
}
-
-/*std::vector<ExecutableInfo> Fallout3Info::getExecutables()
-{
- std::vector<ExecutableInfo> result;
- result.push_back(ExecutableInfo(L"FOSE", L"fose_loader.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Fallout 3", L"fallout3.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Fallout Mod Manager", L"fomm/fomm.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Construction Kit", L"geck.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Fallout Launcher", L"FalloutLauncher.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"BOSS", L"BOSS/BOSS.exe", L"", L"", NEVER_CLOSE));
-
- return result;
-}*/
} // namespace MOShared
diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h
index 7e39cce4..6a211d4f 100644
--- a/src/shared/fallout3info.h
+++ b/src/shared/fallout3info.h
@@ -50,11 +50,6 @@ public:
virtual bool isInvalidationBSA(const std::wstring &bsaName);
- // full path to this games "My Games"-directory
- virtual std::wstring getDocumentsDir();
-
- virtual std::wstring getSaveGameDir();
-
virtual std::vector<std::wstring> getPrimaryPlugins();
virtual std::vector<std::wstring> getVanillaBSAs();
@@ -64,12 +59,10 @@ public:
// file name of this games ini (no path)
virtual std::vector<std::wstring> getIniFileNames();
- virtual std::wstring getSaveGameExtension();
virtual std::wstring getReferenceDataFile();
virtual std::wstring getOMODExt();
virtual std::vector<std::wstring> getSteamVariants() const;
- virtual std::wstring getSteamAPPId(int variant = 0) const;
virtual std::wstring getSEName();
@@ -80,9 +73,6 @@ public:
virtual int getNexusModID() { return getNexusModIDStatic(); }
virtual int getNexusGameID() { return 120; }
- virtual void createProfile(const std::wstring &directory, bool useDefaults);
- virtual void repairProfile(const std::wstring &directory);
-
virtual bool rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath);
// get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp
index f589124a..8e701887 100644
--- a/src/shared/falloutnvinfo.cpp
+++ b/src/shared/falloutnvinfo.cpp
@@ -85,21 +85,6 @@ bool FalloutNVInfo::isInvalidationBSA(const std::wstring &bsaName)
return false;
}
-std::wstring FalloutNVInfo::getDocumentsDir()
-{
- std::wostringstream temp;
- temp << getMyGamesDirectory() << L"\\FalloutNV";
-
- return temp.str();
-}
-
-std::wstring FalloutNVInfo::getSaveGameDir()
-{
- std::wostringstream temp;
- temp << getDocumentsDir() << L"\\Saves";
- return temp.str();
-}
-
std::vector<std::wstring> FalloutNVInfo::getPrimaryPlugins()
{
return boost::assign::list_of(L"falloutnv.esm");
@@ -139,11 +124,6 @@ std::vector<std::wstring> FalloutNVInfo::getIniFileNames()
return boost::assign::list_of(L"fallout.ini")(L"falloutprefs.ini");
}
-std::wstring FalloutNVInfo::getSaveGameExtension()
-{
- return L"*.fos";
-}
-
std::wstring FalloutNVInfo::getReferenceDataFile()
{
return L"Fallout - Meshes.bsa";
@@ -156,61 +136,6 @@ std::wstring FalloutNVInfo::getOMODExt()
}
-std::wstring FalloutNVInfo::getSteamAPPId(int) const
-{
- return L"22380";
-}
-
-
-void FalloutNVInfo::createProfile(const std::wstring &directory, bool useDefaults)
-{
- std::wstring target = directory + L"\\plugins.txt";
-
- // copy plugins.txt
- if (!FileExists(target)) {
- std::wstring source = getLocalAppFolder() + L"\\FalloutNV\\plugins.txt";
- if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
- HANDLE file = ::CreateFileW(target.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
- ::CloseHandle(file);
- }
- }
-
- // copy ini-file
- target = directory + L"\\fallout.ini";
-
- if (!FileExists(target)) {
- std::wstring source;
- if (useDefaults) {
- source = getGameDirectory() + L"\\fallout_default.ini";
- } else {
- source = getMyGamesDirectory() + L"\\FalloutNV";
- if (FileExists(source, L"fallout.ini")) {
- source += L"\\fallout.ini";
- } else {
- source = getGameDirectory() + L"\\fallout_default.ini";
- }
- }
-
- if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
- if (::GetLastError() != ERROR_FILE_EXISTS) {
- throw windows_error("failed to copy ini file: " + ToString(source, false));
- }
- }
- }
- { // copy falloutprefs.ini-file
- std::wstring target = directory + L"\\falloutprefs.ini";
- if (!FileExists(target)) {
- std::wstring source = getMyGamesDirectory() + L"\\FalloutNV\\falloutprefs.ini";
- if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
- if (::GetLastError() != ERROR_FILE_EXISTS) {
- throw windows_error("failed to copy ini file: " + ToString(source, false));
- }
- }
- }
- }
-}
-
-
std::wstring FalloutNVInfo::getSEName()
{
return L"nvse";
@@ -239,12 +164,6 @@ int FalloutNVInfo::getNexusModIDStatic()
}
-void FalloutNVInfo::repairProfile(const std::wstring &directory)
-{
- createProfile(directory, false);
-}
-
-
bool FalloutNVInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t*)
{
static LPCWSTR profileFiles[] = { L"fallout.ini", L"falloutprefs.ini", L"plugins.txt", nullptr };
diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h
index 231311de..513b7218 100644
--- a/src/shared/falloutnvinfo.h
+++ b/src/shared/falloutnvinfo.h
@@ -52,11 +52,6 @@ public:
virtual bool isInvalidationBSA(const std::wstring &bsaName);
- // full path to this games "My Games"-directory
- virtual std::wstring getDocumentsDir();
-
- virtual std::wstring getSaveGameDir();
-
virtual std::vector<std::wstring> getPrimaryPlugins();
virtual std::vector<std::wstring> getVanillaBSAs();
@@ -66,12 +61,9 @@ public:
// file name of this games ini (no path)
virtual std::vector<std::wstring> getIniFileNames();
- virtual std::wstring getSaveGameExtension();
virtual std::wstring getReferenceDataFile();
virtual std::wstring getOMODExt();
- virtual std::wstring getSteamAPPId(int variant = 0) const;
-
virtual std::wstring getSEName();
virtual std::wstring getNexusPage(bool nmmScheme = true);
@@ -81,9 +73,6 @@ public:
virtual int getNexusModID() { return getNexusModIDStatic(); }
virtual int getNexusGameID() { return 130; }
- virtual void createProfile(const std::wstring &directory, bool useDefaults);
- virtual void repairProfile(const std::wstring &directory);
-
virtual bool rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath);
// get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
diff --git a/src/shared/gameinfo.cpp b/src/shared/gameinfo.cpp
index 3727ea49..6d8957ad 100644
--- a/src/shared/gameinfo.cpp
+++ b/src/shared/gameinfo.cpp
@@ -135,49 +135,9 @@ std::wstring GameInfo::getGameDirectory() const
return m_GameDirectory;
}
-std::wstring GameInfo::getModsDir() const
-{
- return m_OrganizerDirectory + L"\\mods";
-}
-
-std::wstring GameInfo::getProfilesDir() const
-{
- return m_OrganizerDirectory + L"\\profiles";
-}
-
-std::wstring GameInfo::getIniFilename() const
-{
- return m_OrganizerDirectory + L"\\ModOrganizer.ini";
-}
-
-
-std::wstring GameInfo::getOverwriteDir() const
-{
- return m_OrganizerDirectory + L"\\overwrite";
-}
-
-
-std::wstring GameInfo::getLogDir() const
-{
- return m_OrganizerDirectory + L"\\logs";
-}
-
-
-std::wstring GameInfo::getLootDir() const
-{
- return m_OrganizerDirectory + L"\\loot";
-}
-
-
-std::wstring GameInfo::getTutorialDir() const
-{
- return m_OrganizerDirectory + L"\\tutorials";
-}
-
-
bool GameInfo::requiresSteam() const
{
- return FileExists(getGameDirectory().append(L"\\steam_api.dll"));
+ return FileExists(getGameDirectory() + L"\\steam_api.dll");
}
std::vector<std::wstring> GameInfo::getSteamVariants() const
@@ -185,7 +145,6 @@ std::vector<std::wstring> GameInfo::getSteamVariants() const
return boost::assign::list_of(L"Regular");
}
-
std::wstring GameInfo::getLocalAppFolder() const
{
wchar_t localAppFolder[MAX_PATH];
diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h
index a9da0b97..dbb935f6 100644
--- a/src/shared/gameinfo.h
+++ b/src/shared/gameinfo.h
@@ -93,18 +93,13 @@ public:
virtual std::wstring getGameName() const = 0;
virtual std::wstring getGameShortName() const = 0;
- // full path to this games "My Games"-directory
- virtual std::wstring getDocumentsDir() = 0;
-
- virtual std::wstring getSaveGameDir() = 0;
-
/// determine the load order mechanism used by this game. this may throw an
/// exception if the mechanism can't be determined
virtual LoadOrderMechanism getLoadOrderMechanism() const { return TYPE_FILETIME; }
virtual std::wstring getGameDirectory() const;
// get absolute path to the directory where omo stores its mods
- virtual std::wstring getModsDir() const;
+/* virtual std::wstring getModsDir() const;
// get absolute path to the directory where omo stores its profiles
virtual std::wstring getProfilesDir() const;
@@ -112,7 +107,7 @@ public:
virtual std::wstring getOverwriteDir() const;
virtual std::wstring getLogDir() const;
virtual std::wstring getLootDir() const;
- virtual std::wstring getTutorialDir() const;
+ virtual std::wstring getTutorialDir() const;*/
virtual bool requiresBSAInvalidation() const { return true; }
virtual bool requiresSteam() const;
@@ -137,13 +132,11 @@ public:
// file name of this games ini file(s)
virtual std::vector<std::wstring> getIniFileNames() = 0;
- virtual std::wstring getSaveGameExtension() = 0;
virtual std::wstring getReferenceDataFile() = 0;
virtual std::wstring getOMODExt() = 0;
virtual std::vector<std::wstring> getSteamVariants() const;
- virtual std::wstring getSteamAPPId(int variant = 0) const = 0;
virtual std::wstring getSEName() = 0;
@@ -152,10 +145,6 @@ public:
virtual int getNexusModID() = 0;
virtual int getNexusGameID() = 0;
- // clone relevant files to the specified directory
- virtual void createProfile(const std::wstring &directory, bool useDefaults) = 0;
- virtual void repairProfile(const std::wstring &directory) = 0;
-
virtual bool rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath) = 0;
public:
diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp
index 586bcaef..c945dcf4 100644
--- a/src/shared/oblivioninfo.cpp
+++ b/src/shared/oblivioninfo.cpp
@@ -86,22 +86,6 @@ bool OblivionInfo::isInvalidationBSA(const std::wstring &bsaName)
return false;
}
-std::wstring OblivionInfo::getDocumentsDir()
-{
- std::wostringstream temp;
- temp << getMyGamesDirectory() << L"\\Oblivion";
-
- return temp.str();
-}
-
-std::wstring OblivionInfo::getSaveGameDir()
-{
- std::wostringstream temp;
- temp << getDocumentsDir() << L"\\Saves";
- return temp.str();
-}
-
-
std::vector<std::wstring> OblivionInfo::getPrimaryPlugins()
{
return boost::assign::list_of(L"oblivion.esm");
@@ -147,63 +131,6 @@ std::vector<std::wstring> OblivionInfo::getIniFileNames()
}
-void OblivionInfo::createProfile(const std::wstring &directory, bool useDefaults)
-{
- std::wostringstream target;
-
- // copy plugins.txt
- target << directory << "\\plugins.txt";
-
- if (!FileExists(target.str())) {
- std::wostringstream source;
- source << getLocalAppFolder() << "\\Oblivion\\plugins.txt";
- if (!::CopyFileW(source.str().c_str(), target.str().c_str(), true)) {
- HANDLE file = ::CreateFileW(target.str().c_str(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
- ::CloseHandle(file);
- }
- }
-
- // copy ini-file
- target.str(L""); target.clear();
- target << directory << L"\\oblivion.ini";
-
- if (!FileExists(target.str())) {
- std::wostringstream source;
- if (useDefaults) {
- source << getGameDirectory() << L"\\oblivion_default.ini";
- } else {
- source << getMyGamesDirectory() << L"Oblivion";
- if (FileExists(source.str(), L"oblivion.ini")) {
- source << L"\\oblivion.ini";
- } else {
- source.str(L"");
- source << getGameDirectory() << L"\\oblivion_default.ini";
- }
- }
- if (!::CopyFileW(source.str().c_str(), target.str().c_str(), true)) {
- if (::GetLastError() != ERROR_FILE_EXISTS) {
- std::ostringstream stream;
- stream << "failed to copy ini file: " << ToString(source.str(), false);
- throw windows_error(stream.str());
- }
- }
- }
-
- { // copy oblivionprefs.ini-file
- std::wstring target = directory + L"\\oblivionprefs.ini";
- if (!FileExists(target)) {
- std::wstring source = getMyGamesDirectory() + L"\\Oblivion\\oblivionprefs.ini";
- if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
- if ((::CreateFileW(target.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr) == INVALID_HANDLE_VALUE) &&
- (::GetLastError() != ERROR_FILE_EXISTS)) {
- throw windows_error(std::string("failed to create ini file: ") + ToString(target, false));
- }
- }
- }
- }
-}
-
-
std::wstring OblivionInfo::getSEName()
{
return L"obse";
@@ -231,13 +158,6 @@ int OblivionInfo::getNexusModIDStatic()
return 38277;
}
-
-void OblivionInfo::repairProfile(const std::wstring &directory)
-{
- createProfile(directory, false);
-}
-
-
bool OblivionInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t*)
{
static LPCWSTR profileFiles[] = { L"oblivion.ini", L"oblivionprefs.ini", L"plugins.txt", nullptr };
@@ -250,12 +170,6 @@ bool OblivionInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t*)
return false;
}
-
-std::wstring OblivionInfo::getSaveGameExtension()
-{
- return L"*.ess";
-}
-
std::wstring OblivionInfo::getReferenceDataFile()
{
return L"Oblivion - Meshes.bsa";
@@ -268,23 +182,4 @@ std::wstring OblivionInfo::getOMODExt()
}
-std::wstring OblivionInfo::getSteamAPPId(int) const
-{
- return L"22330";
-}
-
-/*
-std::vector<ExecutableInfo> OblivionInfo::getExecutables()
-{
- std::vector<ExecutableInfo> result;
- result.push_back(ExecutableInfo(L"OBSE", L"obse_loader.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Oblivion", L"oblivion.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Oblivion Mod Manager", L"OblivionModManager.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Construction Set", L"TESConstructionSet.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Oblivion Launcher", L"OblivionLauncher.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"BOSS", L"BOSS/BOSS.exe", L"", L"", NEVER_CLOSE));
- result.push_back(ExecutableInfo(L"BOSS (old)", L"Data/BOSS.exe", L"", L"", NEVER_CLOSE));
-
- return result;
-}*/
} // namespace MOShared
diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h
index cb506c01..a93f510e 100644
--- a/src/shared/oblivioninfo.h
+++ b/src/shared/oblivioninfo.h
@@ -48,11 +48,6 @@ public:
virtual bool isInvalidationBSA(const std::wstring &bsaName);
- // full path to this games "My Games"-directory
- virtual std::wstring getDocumentsDir();
-
- virtual std::wstring getSaveGameDir();
-
virtual std::vector<std::wstring> getPrimaryPlugins();
virtual std::vector<std::wstring> getVanillaBSAs();
@@ -62,12 +57,9 @@ public:
// file name of this games ini (no path)
virtual std::vector<std::wstring> getIniFileNames();
- virtual std::wstring getSaveGameExtension();
virtual std::wstring getReferenceDataFile();
virtual std::wstring getOMODExt();
- virtual std::wstring getSteamAPPId(int variant = 0) const;
-
virtual std::wstring getSEName();
virtual std::wstring getNexusPage(bool nmmScheme = true);
@@ -77,9 +69,6 @@ public:
virtual int getNexusModID() { return getNexusModIDStatic(); }
virtual int getNexusGameID() { return 101; }
- virtual void createProfile(const std::wstring &directory, bool useDefaults);
- virtual void repairProfile(const std::wstring &directory);
-
virtual bool rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath);
// get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp
index 1d00c4f3..feaf88a3 100644
--- a/src/shared/skyriminfo.cpp
+++ b/src/shared/skyriminfo.cpp
@@ -97,7 +97,7 @@ bool SkyrimInfo::isInvalidationBSA(const std::wstring &bsaName)
GameInfo::LoadOrderMechanism SkyrimInfo::getLoadOrderMechanism() const
{
- std::wstring fileName = getGameDirectory().append(L"\\TESV.exe");
+ std::wstring fileName = getGameDirectory() + L"\\TESV.exe";
try {
VS_FIXEDFILEINFO versionInfo = GetFileVersion(fileName);
@@ -113,21 +113,6 @@ GameInfo::LoadOrderMechanism SkyrimInfo::getLoadOrderMechanism() const
}
}
-std::wstring SkyrimInfo::getDocumentsDir()
-{
- std::wostringstream temp;
- temp << getMyGamesDirectory() << L"\\Skyrim";
-
- return temp.str();
-}
-
-std::wstring SkyrimInfo::getSaveGameDir()
-{
- std::wostringstream temp;
- temp << getDocumentsDir() << L"\\Saves";
- return temp.str();
-}
-
std::vector<std::wstring> SkyrimInfo::getPrimaryPlugins()
{
return boost::assign::list_of(L"skyrim.esm")(L"update.esm");
@@ -170,11 +155,6 @@ std::vector<std::wstring> SkyrimInfo::getIniFileNames()
return boost::assign::list_of(L"skyrim.ini")(L"skyrimprefs.ini");
}
-std::wstring SkyrimInfo::getSaveGameExtension()
-{
- return L"*.ess";
-}
-
std::wstring SkyrimInfo::getReferenceDataFile()
{
return L"Skyrim - Meshes.bsa";
@@ -186,13 +166,6 @@ std::wstring SkyrimInfo::getOMODExt()
return L"fomod";
}
-
-std::wstring SkyrimInfo::getSteamAPPId(int) const
-{
- return L"72850";
-}
-
-
std::wstring SkyrimInfo::getSEName()
{
return L"skse";
@@ -220,73 +193,6 @@ int SkyrimInfo::getNexusModIDStatic()
return 1334;
}
-
-void SkyrimInfo::createProfile(const std::wstring &directory, bool useDefaults)
-{
- { // copy plugins.txt
- std::wstring target = directory + L"\\plugins.txt";
- if (!FileExists(target)) {
- std::wostringstream source;
- source << getLocalAppFolder() << "\\Skyrim\\plugins.txt";
- if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) {
- HANDLE file = ::CreateFileW(target.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
- ::CloseHandle(file);
- }
- }
- target = directory + L"\\loadorder.txt";
- if (!FileExists(target)) {
- std::wstring source = getLocalAppFolder() + L"\\Skyrim\\loadorder.txt";
- if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
- HANDLE file = ::CreateFileW(target.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
- ::CloseHandle(file);
- }
- }
- }
-
- { // copy skyrim.ini-file
- std::wstring target = directory + L"\\skyrim.ini";
- if (!FileExists(target)) {
- std::wstring source;
- if (useDefaults) {
- source = getGameDirectory() + L"\\skyrim_default.ini";
- } else {
- source = getMyGamesDirectory() + L"\\Skyrim";
- if (FileExists(source, L"skyrim.ini")) {
- source += L"\\skyrim.ini";
- } else {
- source = getGameDirectory() + L"\\skyrim_default.ini";
- }
- }
- if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
- if (::GetLastError() != ERROR_FILE_EXISTS) {
- throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false) + " to " + ToString(target, false));
- }
- }
- }
- }
-
- { // copy skyrimprefs.ini-file
- std::wstring target = directory + L"\\skyrimprefs.ini";
- if (!FileExists(target)) {
- std::wstring source = getMyGamesDirectory() + L"\\Skyrim\\skyrimprefs.ini";
- if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
- log("failed to copy ini file %ls", source.c_str());
- // create empty
- if (::CreateFileW(target.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr) == INVALID_HANDLE_VALUE) {
- throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false));
- }
- }
- }
- }
-}
-
-
-void SkyrimInfo::repairProfile(const std::wstring &directory)
-{
- createProfile(directory, false);
-}
-
-
bool SkyrimInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath)
{
static LPCWSTR profileFiles[] = { L"skyrim.ini", L"skyrimprefs.ini", L"loadorder.txt", nullptr };
@@ -306,17 +212,4 @@ bool SkyrimInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPa
}
-/*std::vector<ExecutableInfo> SkyrimInfo::getExecutables()
-{
- std::vector<ExecutableInfo> result;
- result.push_back(ExecutableInfo(L"SKSE", L"skse_loader.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"SBW", L"SBW.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Skyrim", L"TESV.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"Skyrim Launcher", L"SkyrimLauncher.exe", L"", L"", DEFAULT_CLOSE));
- result.push_back(ExecutableInfo(L"BOSS", L"BOSS/BOSS.exe", L"", L"", DEFAULT_STAY));
- result.push_back(ExecutableInfo(L"Creation Kit", L"CreationKit.exe", L"", L"", DEFAULT_STAY, L"202480"));
-
- return result;
-}*/
-
} // namespace MOShared
diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h
index ad6ab95d..bf08fb25 100644
--- a/src/shared/skyriminfo.h
+++ b/src/shared/skyriminfo.h
@@ -49,17 +49,11 @@ public:
virtual LoadOrderMechanism getLoadOrderMechanism() const;
virtual bool requiresBSAInvalidation() const { return true; }
-// virtual bool requiresSteam() const { return true; }
virtual std::wstring getInvalidationBSA();
virtual bool isInvalidationBSA(const std::wstring &bsaName);
- // full path to this games "My Games"-directory
- virtual std::wstring getDocumentsDir();
-
- virtual std::wstring getSaveGameDir();
-
virtual std::vector<std::wstring> getPrimaryPlugins();
virtual std::vector<std::wstring> getVanillaBSAs();
@@ -70,12 +64,9 @@ public:
// file name of this games ini (no path)
virtual std::vector<std::wstring> getIniFileNames();
- virtual std::wstring getSaveGameExtension();
virtual std::wstring getReferenceDataFile();
virtual std::wstring getOMODExt();
- virtual std::wstring getSteamAPPId(int variant = 0) const;
-
virtual std::wstring getSEName();
virtual std::wstring getNexusPage(bool nmmScheme = true);
@@ -87,15 +78,8 @@ public:
static int getNexusGameIDStatic() { return 110; }
virtual int getNexusGameID() { return getNexusGameIDStatic(); }
- virtual void createProfile(const std::wstring &directory, bool useDefaults);
- virtual void repairProfile(const std::wstring &directory);
-
virtual bool rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath);
- // get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
- // the game directory
- //virtual std::vector<ExecutableInfo> getExecutables();
-
virtual std::wstring archiveListKey() { return L"SResourceArchiveList"; }
private:
diff --git a/src/transfersavesdialog.cpp b/src/transfersavesdialog.cpp
index b07b1673..5d20c253 100644
--- a/src/transfersavesdialog.cpp
+++ b/src/transfersavesdialog.cpp
@@ -31,8 +31,11 @@ using namespace MOBase;
using namespace MOShared;
-TransferSavesDialog::TransferSavesDialog(const Profile &profile, QWidget *parent)
- : TutorableDialog("TransferSaves", parent), ui(new Ui::TransferSavesDialog), m_Profile(profile)
+TransferSavesDialog::TransferSavesDialog(const Profile &profile, IPluginGame *gamePlugin, QWidget *parent)
+ : TutorableDialog("TransferSaves", parent)
+ , ui(new Ui::TransferSavesDialog)
+ , m_Profile(profile)
+ , m_GamePlugin(gamePlugin)
{
ui->setupUi(this);
refreshGlobalSaves();
@@ -51,10 +54,10 @@ void TransferSavesDialog::refreshGlobalSaves()
{
m_GlobalSaves.clear();
- QDir savesDir(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getSaveGameDir())));
+ QDir savesDir(m_GamePlugin->savesDirectory());
QStringList filters;
- filters << ToQString(GameInfo::instance().getSaveGameExtension());
+ filters << m_GamePlugin->savegameExtension();
savesDir.setNameFilters(filters);
QStringList files = savesDir.entryList(QDir::Files, QDir::Time);
@@ -71,10 +74,10 @@ void TransferSavesDialog::refreshLocalSaves()
{
m_LocalSaves.clear();
- QDir savesDir(m_Profile.getPath().append("/saves"));
+ QDir savesDir(m_Profile.getPath() + "/saves");
QStringList filters;
- filters << ToQString(GameInfo::instance().getSaveGameExtension());
+ filters << m_GamePlugin->savegameExtension();
savesDir.setNameFilters(filters);
QStringList files = savesDir.entryList(QDir::Files, QDir::Time);
@@ -232,7 +235,7 @@ void TransferSavesDialog::on_moveToGlobalBtn_clicked()
"that this will mess up the running number of save games.").arg(selectedCharacter),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- QString destination = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getSaveGameDir()));
+ QDir destination = m_GamePlugin->savesDirectory();
OverwriteMode overwriteMode = OVERWRITE_ASK;
for (std::vector<SaveGame*>::const_iterator iter = m_LocalSaves.begin();
iter != m_LocalSaves.end(); ++iter) {
@@ -240,7 +243,7 @@ void TransferSavesDialog::on_moveToGlobalBtn_clicked()
QStringList files = (*iter)->saveFiles();
foreach (const QString &file, files) {
QFileInfo fileInfo(file);
- QString destinationFile = destination.mid(0).append("/").append(fileInfo.fileName());
+ QString destinationFile = destination.filePath(fileInfo.fileName());
if (QFile::exists(destinationFile)) {
if (testOverwrite(overwriteMode, destinationFile)) {
QFile::remove(destinationFile);
@@ -271,7 +274,7 @@ void TransferSavesDialog::on_copyToGlobalBtn_clicked()
"that this will mess up the running number of save games.").arg(selectedCharacter),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- QString destination = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getSaveGameDir()));
+ QDir destination = m_GamePlugin->savesDirectory();
OverwriteMode overwriteMode = OVERWRITE_ASK;
for (std::vector<SaveGame*>::const_iterator iter = m_LocalSaves.begin();
iter != m_LocalSaves.end(); ++iter) {
@@ -279,7 +282,7 @@ void TransferSavesDialog::on_copyToGlobalBtn_clicked()
QStringList files = (*iter)->saveFiles();
foreach (const QString &file, files) {
QFileInfo fileInfo(file);
- QString destinationFile = destination.mid(0).append("/").append(fileInfo.fileName());
+ QString destinationFile = destination.filePath(fileInfo.fileName());
if (QFile::exists(destinationFile)) {
if (testOverwrite(overwriteMode, destinationFile)) {
QFile::remove(destinationFile);
diff --git a/src/transfersavesdialog.h b/src/transfersavesdialog.h
index 37a85000..4d466bf2 100644
--- a/src/transfersavesdialog.h
+++ b/src/transfersavesdialog.h
@@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "tutorabledialog.h"
#include "savegamegamebyro.h"
#include "profile.h"
+#include <iplugingame.h>
namespace Ui {
class TransferSavesDialog;
@@ -33,7 +34,7 @@ class TransferSavesDialog : public MOBase::TutorableDialog
Q_OBJECT
public:
- explicit TransferSavesDialog(const Profile &profile, QWidget *parent = 0);
+ explicit TransferSavesDialog(const Profile &profile, MOBase::IPluginGame *gamePlugin, QWidget *parent = 0);
~TransferSavesDialog();
private slots:
@@ -74,6 +75,8 @@ private:
Profile m_Profile;
+ MOBase::IPluginGame *m_GamePlugin;
+
std::vector<SaveGame*> m_GlobalSaves;
std::vector<SaveGame*> m_LocalSaves;
diff --git a/src/tutorials/Highlight.qml b/src/tutorials/Highlight.qml
index bb4db78f..55474c91 100644
--- a/src/tutorials/Highlight.qml
+++ b/src/tutorials/Highlight.qml
@@ -1,4 +1,3 @@
-// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
diff --git a/src/tutorials/Tooltip.qml b/src/tutorials/Tooltip.qml
new file mode 100644
index 00000000..6424d9ab
--- /dev/null
+++ b/src/tutorials/Tooltip.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.1
+
+
+Rectangle {
+ color: "#EE888888"
+ width: childrenRect.width + 15
+ height: childrenRect.height + 15
+ z: 20000
+ clip: false
+ border.color: "black"
+ border.width: 1
+ property alias text: tooltipText.text
+ Text {
+ id: tooltipText
+ font.pointSize: 11
+ wrapMode: Text.WordWrap
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.leftMargin: 7
+ anchors.rightMargin: 7
+ z: parent.z
+ color: "black"
+ onTextChanged: {
+ if (width > 200)
+ width = 200
+ }
+ }
+ visible: false
+}
+
+
diff --git a/src/tutorials/TooltipArea.qml b/src/tutorials/TooltipArea.qml
new file mode 100644
index 00000000..48a50f76
--- /dev/null
+++ b/src/tutorials/TooltipArea.qml
@@ -0,0 +1,55 @@
+import QtQuick 1.1
+
+Rectangle {
+ radius: 2
+ color: clickable ? "#AA6666AA" : "#AA882222"
+ height: 100
+ border.color: "black"
+ border.width: 2
+ z: 1
+ smooth: true
+ property bool wasLocked: false
+ property bool clickable: false
+ property string tooltipText: ""
+
+ MouseArea {
+ id: clickArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ onMousePositionChanged: {
+ if (parent.parent.width - (parent.x + mouseX) < tooltip.width + 50) {
+ tooltip.x = parent.x + mouseX - 15 - tooltip.width
+ } else {
+ tooltip.x = parent.x + mouseX + 15
+ }
+
+ if (parent.parent.height - (parent.y + mouseY) < tooltip.height + 50) {
+ tooltip.y = parent.y + mouseY - 15 - tooltip.height
+ } else {
+ tooltip.y = parent.y + mouseY + 15
+ }
+ }
+
+ onEntered: {
+ tooltip.visible = true
+ tooltip.text = tooltipText
+ }
+
+ onPressed: {
+ wasLocked = tutToplevel.backgroundEnabled()
+ if (wasLocked && clickable) {
+ tutorialControl.simulateClick(mouseX + parent.x, mouseY + parent.y)
+ }
+ mouse.accepted = false
+ }
+
+ onCanceled: {
+ tooltip.visible = false
+ }
+
+ onExited: {
+ tooltip.visible = false
+ }
+ }
+}
diff --git a/src/tutorials/TutorialDescription.qml b/src/tutorials/TutorialDescription.qml
index b295e477..498573d2 100644
--- a/src/tutorials/TutorialDescription.qml
+++ b/src/tutorials/TutorialDescription.qml
@@ -15,8 +15,9 @@ Rectangle {
border.color: "black"
border.width: 3
smooth: true
- opacity: 0.9
- color: "#707070"
+ //opacity: 0.9
+ z: 10000
+ color: "#FF707070"
Image {
id: continueIcon
diff --git a/src/tutorials/TutorialOverlay.qml b/src/tutorials/TutorialOverlay.qml
index f2aad027..15fe9603 100644
--- a/src/tutorials/TutorialOverlay.qml
+++ b/src/tutorials/TutorialOverlay.qml
@@ -2,52 +2,67 @@ import QtQuick 1.1
import "tutorials.js" as Logic
Rectangle {
- color: "transparent"
+ color: "transparent"
- property int step : 0
- property alias description: tutDescription
- property alias highlight: tutHighlight
- property alias text: tutDescription.text
- property alias boxOpacity: tutDescription.opacity
- property int offsetBottom: 50
- property int maxWidth: 400
+ id: tutToplevel
- function init() {
- Logic.init()
- Logic.nextStep()
- }
+ property int step : 0
+ property alias description: tutDescription
+ property alias highlight: tutHighlight
+ property alias text: tutDescription.text
+ property alias boxOpacity: tutDescription.opacity
+ property int offsetBottom: 50
+ property int maxWidth: 400
- function enableBackground(enabled) {
- disabledBackground.visible = enabled
- }
-/*
- signal nextStep
+ signal tabChanged(int index)
- onNextStep: {*/
- function nextStep() {
- if (step == 0) {
- Logic.init()
- }
+ function init() {
+ Logic.init()
+ Logic.nextStep()
+ }
- Logic.nextStep()
- }
+ function enableBackground(enabled) {
+ disabledBackground.visible = enabled
+ }
+
+ function backgroundEnabled() {
+ return disabledBackground.visible
+ }
- TutorialDescription {
- id: tutDescription
- innerWidth: maxWidth
- anchors.bottomMargin: offsetBottom
- onClicked: {
- Logic.clickNext()
- }
+ function nextStep() {
+ if (step == 0) {
+ Logic.init()
}
- Rectangle {
- id: disabledBackground
- anchors.fill: parent
- opacity: 0.2
- color: "#808080"
+ Logic.nextStep()
+ }
+
+ TutorialDescription {
+ id: tutDescription
+ innerWidth: maxWidth
+ anchors.bottomMargin: offsetBottom
+ onClicked: {
+ Logic.clickNext()
}
+ }
+
+ Rectangle {
+ id: disabledBackground
+ anchors.fill: parent
+ opacity: 0.2
+ color: "#808080"
+ }
+
+ Connections {
+ target: manager
+ onTabChanged: tabChanged(index)
+ }
- Highlight { id: tutHighlight }
+ Tooltip {
+ id: tooltip
+ }
+ Highlight {
+ id: tutHighlight
+ }
}
diff --git a/src/tutorials/tutorial_primer_main.js b/src/tutorials/tutorial_primer_main.js
new file mode 100644
index 00000000..12df2c86
--- /dev/null
+++ b/src/tutorials/tutorial_primer_main.js
@@ -0,0 +1,111 @@
+//TL Overview#5
+
+
+var tooltips = []
+
+function tooltipWidget(widgetName, explanation, maxheight, clickable) {
+ var rect = tutorialControl.getRect(widgetName)
+ var component = Qt.createComponent("TooltipArea.qml")
+ if (component.status === Component.Error) {
+ console.log("b" + component.errorString())
+ }
+ if (typeof clickable === 'undefined') {
+ clickable = false
+ }
+ if ((typeof maxheight === 'undefined') || maxheight === 0) {
+ maxheight = rect.height
+ }
+
+ var obj = component.createObject(tutToplevel,
+ { "x" : rect.x,
+ "y" : rect.y,
+ "width" : rect.width,
+ "height" : maxheight
+ })
+ obj.tooltipText = explanation
+ obj.clickable = clickable
+ obj.visible = true
+
+ tooltips.push(obj)
+}
+
+function tooltipAction(actionName, explanation, maxheight, clickable) {
+ var rect = tutorialControl.getActionRect(actionName)
+ var component = Qt.createComponent("TooltipArea.qml")
+ if (typeof clickable === 'undefined') {
+ clickable = false
+ }
+ if ((typeof maxheight === 'undefined') || maxheight === 0) {
+ maxheight = rect.height
+ }
+ var obj = component.createObject(tutToplevel,
+ { "x" : rect.x,
+ "y" : rect.y,
+ "width" : rect.width,
+ "height" : maxheight
+ })
+ obj.tooltipText = explanation
+ obj.clickable = clickable
+ obj.visible = true
+
+ tooltips.push(obj)
+}
+
+function setupTooptips() {
+ for (var tip in tooltips) {
+ tooltips[tip].destroy()
+ }
+ tooltips = []
+
+ tooltipWidget("modList", qsTr("This window shows all the mods that are installed. The column headers can be used for sorting. Only checked mods are active in the current profile."))
+ tooltipWidget("profileBox", qsTr("Each profile is a separate set of enabled mods and ini settings."))
+ tooltipWidget("groupCombo", qsTr("The dropdown allows various ways of grouping the mods shown in the mod list."))
+ tooltipWidget("displayCategoriesBtn", qsTr("Show/hide the category pane."))
+ tooltipWidget("modFilterEdit", qsTr("Quickly filter the mod list as you type."))
+ tooltipWidget("qt_tabwidget_tabbar", qsTr("Switch between information views."), 0, true)
+ tooltipWidget("categoriesList", qsTr("This shows mod categories and some meta categories (in angle-brackets). Select some to filter the mod list. For example select \"<Checked>\" to show only active mods."))
+ tooltipWidget("executablesListBox", qsTr("Customizable list for choosing the program to run."))
+ tooltipWidget("startButton", qsTr("When this button is clicked, Mod Organizer creates a virtual directory structure then runs the program selected to the left."))
+ tooltipWidget("linkButton", qsTr("Will create a shortcut for quick access. The shortcut can be placed in the toolbar at the top, in the Start Menu or on the Windows Desktop."))
+ tooltipWidget("logList", qsTr("Log messages produced by MO. Please note that messages with a light bulb usually don't require your attention."))
+
+ tooltipAction("actionSettings", qsTr("Configure Mod Organizer."))
+ tooltipAction("actionProblems", qsTr("Reports potential Problems about the current setup."))
+ tooltipAction("actionUpdate", qsTr("Activates if there is an update for MO. Please note that if, for any reason, MO can't communicate with NMM, this will not work either."))
+
+ switch (manager.findControl("tabWidget").currentIndex) {
+ case 0:
+ tooltipWidget("espList", qsTr("Plugins (esp/esm files) of the mods in the current profile. They need to be checked to be loaded."))
+ tooltipWidget("bossButton", qsTr("Automatically sort plugins using the bundled LOOT application."))
+ tooltipWidget("espFilterEdit", qsTr("Quickly filter plugin list as you type."))
+ break
+ case 1:
+ tooltipWidget("bsaList", qsTr("All the asset archives (.bsa files) for all active mods."))
+ break
+ case 2:
+ tooltipWidget("dataTree", qsTr("The directory tree and all files that the program will see."))
+ break
+ case 3:
+ tooltipWidget("savegameList", qsTr("Save game browser. Shows all the saves for the current profile and whether or not the current mod-load status is correct."))
+ break
+ case 4:
+ tooltipWidget("downloadView", qsTr("Shows the mods that have been downloaded and if they’ve been installed."))
+ break
+ }
+}
+
+function getTutorialSteps() {
+ return [
+ function() {
+ tutorial.text = qsTr("Click to quit")
+
+ setupTooptips()
+
+ onTabChanged(setupTooptips)
+
+ waitForClick()
+ }
+ ]
+}
+
+
diff --git a/src/tutorials/tutorials.js b/src/tutorials/tutorials.js
index f2b18856..eb23eab7 100644
--- a/src/tutorials/tutorials.js
+++ b/src/tutorials/tutorials.js
@@ -52,15 +52,25 @@ function clickNext()
function nextStep()
{
- waitingForClick = false;
- description.continueVisible = false
- if (step < tutorialSteps.length) {
- tutorialControl.lockUI(false)
- step++
- tutorialSteps[step - 1]()
- } else {
- tutorialControl.finish()
- }
+ waitingForClick = false;
+ description.continueVisible = false
+ if (step < tutorialSteps.length) {
+ tutorialControl.lockUI(false)
+ step++
+ tutorialSteps[step - 1]()
+ } else {
+ tutorialControl.finish()
+ }
+}
+
+function sameStep()
+{
+ tutorialSteps[step - 1]()
+}
+
+function onTabChanged(func)
+{
+ tutToplevel.tabChanged.connect(func)
}
function init()