/* Copyright (C) 2012 Sebastian Herbord. All rights reserved. This file is part of Mod Organizer. Mod Organizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Mod Organizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see . */ #include "executableslist.h" #include "iplugingame.h" #include "utility.h" #include #include #include #include #include using namespace MOBase; ExecutablesList::iterator ExecutablesList::begin() { return m_Executables.begin(); } ExecutablesList::const_iterator ExecutablesList::begin() const { return m_Executables.begin(); } ExecutablesList::iterator ExecutablesList::end() { return m_Executables.end(); } ExecutablesList::const_iterator ExecutablesList::end() const { return m_Executables.end(); } std::size_t ExecutablesList::size() const { return m_Executables.size(); } bool ExecutablesList::empty() const { return m_Executables.empty(); } void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) { qDebug("setting up configured executables"); m_Executables.clear(); int numCustomExecutables = settings.beginReadArray("customExecutables"); for (int i = 0; i < numCustomExecutables; ++i) { settings.setArrayIndex(i); Executable::Flags flags; if (settings.value("toolbar", false).toBool()) flags |= Executable::ShowInToolbar; if (settings.value("ownicon", false).toBool()) flags |= Executable::UseApplicationIcon; setExecutable(Executable() .title(settings.value("title").toString()) .binaryInfo(settings.value("binary").toString()) .arguments(settings.value("arguments").toString()) .steamAppID(settings.value("steamAppID", "").toString()) .workingDirectory(settings.value("workingDirectory", "").toString()) .flags(flags)); } settings.endArray(); addFromPlugin(game, IgnoreExisting); } void ExecutablesList::store(QSettings& settings) { settings.remove("customExecutables"); settings.beginWriteArray("customExecutables"); int count = 0; for (const auto& item : *this) { settings.setArrayIndex(count++); settings.setValue("title", item.title()); settings.setValue("toolbar", item.isShownOnToolbar()); settings.setValue("ownicon", item.usesOwnIcon()); settings.setValue("binary", item.binaryInfo().absoluteFilePath()); settings.setValue("arguments", item.arguments()); settings.setValue("workingDirectory", item.workingDirectory()); settings.setValue("steamAppID", item.steamAppID()); } settings.endArray(); } void ExecutablesList::resetFromPlugin(MOBase::IPluginGame const *game) { qDebug("resetting plugin executables"); addFromPlugin(game, MoveExisting); } void ExecutablesList::addFromPlugin(IPluginGame const *game, SetFlags flags) { Q_ASSERT(game != nullptr); for (const ExecutableInfo &info : game->executables()) { if (!info.isValid()) { continue; } setExecutable({info, Executable::UseApplicationIcon}, flags); } const QFileInfo eppBin(QCoreApplication::applicationDirPath() + "/explorer++/Explorer++.exe"); if (eppBin.exists()) { const auto args = QString("\"%1\"") .arg(QDir::toNativeSeparators(game->dataDirectory().absolutePath())); const auto exe = Executable() .title("Explore Virtual Folder") .binaryInfo(eppBin) .arguments(args) .workingDirectory(eppBin.absolutePath()) .flags(Executable::UseApplicationIcon); setExecutable(exe, flags); } } const Executable &ExecutablesList::get(const QString &title) const { for (const auto& exe : m_Executables) { if (exe.title() == title) { return exe; } } throw std::runtime_error(QString("executable not found: %1").arg(title).toLocal8Bit().constData()); } Executable &ExecutablesList::get(const QString &title) { return const_cast(std::as_const(*this).get(title)); } Executable &ExecutablesList::getByBinary(const QFileInfo &info) { for (Executable &exe : m_Executables) { if (exe.binaryInfo() == info) { return exe; } } throw std::runtime_error("invalid info"); } ExecutablesList::iterator ExecutablesList::find(const QString &title) { return std::find_if(begin(), end(), [&](auto&& e) { return e.title() == title; }); } ExecutablesList::const_iterator ExecutablesList::find(const QString &title) const { return std::find_if(begin(), end(), [&](auto&& e) { return e.title() == title; }); } bool ExecutablesList::titleExists(const QString &title) const { auto test = [&] (const Executable &exe) { return exe.title() == title; }; return std::find_if(m_Executables.begin(), m_Executables.end(), test) != m_Executables.end(); } void ExecutablesList::setExecutable(const Executable &exe) { setExecutable(exe, MergeExisting); } void ExecutablesList::setExecutable(const Executable &exe, SetFlags flags) { auto itor = find(exe.title()); if (itor != end()) { if (flags == IgnoreExisting) { return; } if (flags == MoveExisting) { const auto newTitle = makeNonConflictingTitle(exe.title()); if (!newTitle) { qCritical().nospace() << "executable '" << exe.title() << "' was in the way but could " << "not be renamed"; return; } qWarning().nospace() << "executable '" << itor->title() << "' was in the way and was " << "renamed to '" << *newTitle << "'"; itor->title(*newTitle); itor = end(); } } if (itor == m_Executables.end()) { m_Executables.push_back(exe); } else { itor->mergeFrom(exe); } } void ExecutablesList::remove(const QString &title) { auto itor = find(title); if (itor != m_Executables.end()) { m_Executables.erase(itor); } } std::optional ExecutablesList::makeNonConflictingTitle( const QString& prefix) { const int max = 100; QString title = prefix; for (int i=1; i