mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
352975e757 | ||
|
|
cd83f4e732 | ||
|
|
4f25a0689f | ||
|
|
3d642563cb | ||
|
|
0100c86887 | ||
|
|
8d04c77c29 | ||
|
|
b935ce3862 | ||
|
|
fcebf21c44 | ||
|
|
3d1dfadb40 | ||
|
|
c2c48bd39a | ||
|
|
9163a6dc34 | ||
|
|
8bf3037d4b | ||
|
|
4f1bb36933 | ||
|
|
cbdea13a9c | ||
|
|
b36c666899 | ||
|
|
bbab59f681 | ||
|
|
bfbb190998 | ||
|
|
c3b7737ae4 | ||
|
|
30878ae394 | ||
|
|
45a182a381 | ||
|
|
0b07cfa3f0 | ||
|
|
986330a3bd | ||
|
|
81c5ca5308 | ||
|
|
3a8da159da | ||
|
|
f6c3b516fd | ||
|
|
5665be7fd1 | ||
|
|
e522afa63b | ||
|
|
e3c3c2dcc4 | ||
|
|
519f215fd7 | ||
|
|
89221af929 | ||
|
|
59a36107a1 | ||
|
|
bc5d5d8bfa | ||
|
|
a294f8410f | ||
|
|
ba8464f01f | ||
|
|
0e9a86ebfc | ||
|
|
8da9ba5404 | ||
|
|
387326f2d6 | ||
|
|
d07b4f7ff0 | ||
|
|
197c49e996 | ||
|
|
0d50427b83 | ||
|
|
e90fbb1df2 | ||
|
|
a4dbe82be7 | ||
|
|
42417b6a01 | ||
|
|
f2b2ee1a11 | ||
|
|
ae6bb99c52 | ||
|
|
3869eaaf2b | ||
|
|
6edf12f2f7 | ||
|
|
f55a5f2b21 | ||
|
|
5f5184ebfe | ||
|
|
30b29635f6 | ||
|
|
0c536a4c12 | ||
|
|
967c2ae653 | ||
|
|
ba176e5e9b |
+82
@@ -0,0 +1,82 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[mod-organizer.organizer]
|
||||
file_filter = organizer/organizer_<lang>.ts
|
||||
source_file = organizer/organizer_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.diagnosebasic]
|
||||
file_filter = plugins/diagnoseBasic/diagnoseBasic_<lang>.ts
|
||||
source_file = plugins/diagnoseBasic/diagnoseBasic_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.bsaextractor]
|
||||
file_filter = plugins/bsaExtractor/bsaExtractor_<lang>.ts
|
||||
source_file = plugins/bsaExtractor/bsaExtractor_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.checkfnis]
|
||||
file_filter = plugins/checkFNIS/checkFNIS_<lang>.ts
|
||||
source_file = plugins/checkFNIS/checkFNIS_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.inieditor]
|
||||
file_filter = plugins/iniEditor/iniEditor_<lang>.ts
|
||||
source_file = plugins/iniEditor/iniEditor_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.installerbain]
|
||||
file_filter = plugins/installerBAIN/installerBAIN_<lang>.ts
|
||||
source_file = plugins/installerBAIN/installerBAIN_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.installerbundle]
|
||||
file_filter = plugins/installerBundle/installerBundle_<lang>.ts
|
||||
source_file = plugins/installerBundle/installerBundle_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.installerfomod]
|
||||
file_filter = plugins/installerFomod/installerFomod_<lang>.ts
|
||||
source_file = plugins/installerFomod/installerFomod_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.installermanual]
|
||||
file_filter = plugins/installerManual/installerManual_<lang>.ts
|
||||
source_file = plugins/installerManual/installerManual_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.installerncc]
|
||||
file_filter = plugins/installerNCC/installerNCC_<lang>.ts
|
||||
source_file = plugins/installerNCC/installerNCC_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.installerquick]
|
||||
file_filter = plugins/installerQuick/installerQuick_<lang>.ts
|
||||
source_file = plugins/installerQuick/installerQuick_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.nmmimport]
|
||||
file_filter = plugins/NMMImport/NMMImport_<lang>.ts
|
||||
source_file = plugins/NMMImport/NMMImport_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.previewbase]
|
||||
file_filter = plugins/previewBase/previewBase_<lang>.ts
|
||||
source_file = plugins/previewBase/previewBase_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.previewdds]
|
||||
file_filter = plugins/previewDDS/previewDDS_<lang>.ts
|
||||
source_file = plugins/previewDDS/previewDDS_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.proxypython]
|
||||
file_filter = plugins/proxyPython/proxyPython_<lang>.ts
|
||||
source_file = plugins/proxyPython/proxyPython_en.ts
|
||||
source_lang = en
|
||||
|
||||
[mod-organizer.configurator]
|
||||
file_filter = plugins/pyniEdit/pyniEdit_<lang>.ts
|
||||
source_file = plugins/pyniEdit/pyniEdit_en.ts
|
||||
source_lang = en
|
||||
+3
-3
@@ -86,7 +86,6 @@ SET(organizer_SRCS
|
||||
usvfsconnector.cpp
|
||||
eventfilter.cpp
|
||||
|
||||
shared/inject.cpp
|
||||
shared/windows_error.cpp
|
||||
shared/error_report.cpp
|
||||
shared/directoryentry.cpp
|
||||
@@ -173,7 +172,6 @@ SET(organizer_HDRS
|
||||
usvfsconnector.h
|
||||
eventfilter.h
|
||||
|
||||
shared/inject.h
|
||||
shared/windows_error.h
|
||||
shared/error_report.h
|
||||
shared/directoryentry.h
|
||||
@@ -239,8 +237,10 @@ FIND_PACKAGE(Qt5Declarative REQUIRED)
|
||||
FIND_PACKAGE(Qt5Network REQUIRED)
|
||||
FIND_PACKAGE(Qt5WinExtras REQUIRED)
|
||||
FIND_PACKAGE(Qt5WebKitWidgets REQUIRED)
|
||||
FIND_PACKAGE(Qt5LinguistTools)
|
||||
QT5_WRAP_UI(organizer_UIHDRS ${organizer_UIS})
|
||||
QT5_ADD_RESOURCES(organizer_RCCPPS ${organizer_QRCS})
|
||||
QT5_CREATE_TRANSLATION(organizer_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/organizer_en.ts)
|
||||
|
||||
INCLUDE_DIRECTORIES(${Qt5Declarative_INCLUDES})
|
||||
|
||||
@@ -297,7 +297,7 @@ ELSE()
|
||||
SET(usvfs_name usvfs_x86)
|
||||
ENDIF()
|
||||
|
||||
ADD_EXECUTABLE(ModOrganizer WIN32 ${organizer_HDRS} ${organizer_SRCS} ${organizer_UIHDRS} ${organizer_RCS} ${organizer_RCCPPS})
|
||||
ADD_EXECUTABLE(ModOrganizer WIN32 ${organizer_HDRS} ${organizer_SRCS} ${organizer_UIHDRS} ${organizer_RCS} ${organizer_RCCPPS} ${organizer_translations_qm})
|
||||
TARGET_LINK_LIBRARIES(ModOrganizer
|
||||
Qt5::Widgets Qt5::WinExtras Qt5::WebKitWidgets
|
||||
${Boost_LIBRARIES}
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>746</width>
|
||||
<width>604</width>
|
||||
<height>369</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -151,7 +151,7 @@
|
||||
</widget>
|
||||
<widget class="QWidget" name="credits">
|
||||
<attribute name="title">
|
||||
<string>Credits</string>
|
||||
<string>Thanks</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
@@ -239,7 +239,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Others</string>
|
||||
<string>Other Supporter</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
|
||||
@@ -35,13 +35,8 @@ ActivateModsDialog::ActivateModsDialog(SaveGameInfo::MissingAssets const &missin
|
||||
|
||||
QTableWidget *modsTable = findChild<QTableWidget*>("modsTable");
|
||||
QHeaderView *headerView = modsTable->horizontalHeader();
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
headerView->setSectionResizeMode(1, QHeaderView::Interactive);
|
||||
#else
|
||||
headerView->setResizeMode(0, QHeaderView::Stretch);
|
||||
headerView->setResizeMode(1, QHeaderView::Interactive);
|
||||
#endif
|
||||
|
||||
int row = 0;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>282</width>
|
||||
<width>294</width>
|
||||
<height>156</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -25,29 +25,25 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="usernameEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="passwordEdit">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
<file name="icuin53.dll"/>
|
||||
<file name="icuuc53.dll"/>
|
||||
<file name="icudt53.dll"/>
|
||||
<file name="libeay32.dll"/>
|
||||
<file name="ssleay32.dll"/>
|
||||
<file name="Qt5Core.dll"/>
|
||||
<file name="Qt5Declarative.dll"/>
|
||||
<file name="Qt5Gui.dll"/>
|
||||
|
||||
+12
-9
@@ -757,12 +757,15 @@ QString DownloadManager::getDisplayName(int index) const
|
||||
|
||||
DownloadInfo *info = m_ActiveDownloads.at(index);
|
||||
|
||||
QTextDocument doc;
|
||||
if (!info->m_FileInfo->name.isEmpty()) {
|
||||
return QString("%1 (%2, v%3)").arg(info->m_FileInfo->name)
|
||||
doc.setHtml(info->m_FileInfo->name);
|
||||
return QString("%1 (%2, v%3)").arg(doc.toPlainText())
|
||||
.arg(getFileTypeString(info->m_FileInfo->fileCategory))
|
||||
.arg(info->m_FileInfo->version.displayString());
|
||||
} else {
|
||||
return info->m_FileName;
|
||||
doc.setHtml(info->m_FileName);
|
||||
return doc.toPlainText();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,7 +1061,9 @@ void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant r
|
||||
DownloadInfo *info = downloadInfoByID(userData.toInt());
|
||||
if (info == nullptr) return;
|
||||
info->m_FileInfo->categoryID = result["category_id"].toInt();
|
||||
info->m_FileInfo->modName = result["name"].toString().trimmed();
|
||||
QTextDocument doc;
|
||||
doc.setHtml(result["name"].toString().trimmed());
|
||||
info->m_FileInfo->modName = doc.toPlainText();
|
||||
info->m_FileInfo->newestVersion.parse(result["version"].toString());
|
||||
if (info->m_FileInfo->fileID != 0) {
|
||||
setState(info, STATE_READY);
|
||||
@@ -1116,7 +1121,7 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
|
||||
|
||||
bool found = false;
|
||||
|
||||
foreach(QVariant file, result) {
|
||||
for (QVariant file : result) {
|
||||
QVariantMap fileInfo = file.toMap();
|
||||
QString fileName = fileInfo["uri"].toString();
|
||||
QString fileNameVariant = fileName.mid(0).replace(' ', '_');
|
||||
@@ -1127,12 +1132,10 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
|
||||
if (!info->m_FileInfo->version.isValid()) {
|
||||
info->m_FileInfo->version = info->m_FileInfo->newestVersion;
|
||||
}
|
||||
//Nexus has HTMLd these so unhtml them if necessary
|
||||
// we receive some names html-encoded. This is used to decode it
|
||||
QTextDocument doc;
|
||||
doc.setHtml(info->m_FileInfo->modName);
|
||||
doc.setHtml(fileInfo["modName"].toString());
|
||||
info->m_FileInfo->modName = doc.toPlainText();
|
||||
doc.setHtml(info->m_FileInfo->name);
|
||||
info->m_FileInfo->name = doc.toPlainText();
|
||||
info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt());
|
||||
info->m_FileInfo->fileTime = matchDate(fileInfo["date"].toString());
|
||||
info->m_FileInfo->fileID = fileInfo["id"].toInt();
|
||||
@@ -1148,7 +1151,7 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
|
||||
emit showMessage(tr("No matching file found on Nexus! Maybe this file is no longer available or it was renamed?"));
|
||||
} else {
|
||||
SelectionDialog selection(tr("No file on Nexus matches the selected file by name. Please manually choose the correct one."));
|
||||
foreach(QVariant file, result) {
|
||||
for (QVariant file : result) {
|
||||
QVariantMap fileInfo = file.toMap();
|
||||
selection.addChoice(fileInfo["uri"].toString(), "", file);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ QList<QString> GenericIconDelegate::getIcons(const QModelIndex &index) const
|
||||
{
|
||||
QList<QString> result;
|
||||
if (index.isValid()) {
|
||||
foreach (const QVariant &var, index.data(m_Role).toList()) {
|
||||
for (const QVariant &var : index.data(m_Role).toList()) {
|
||||
if (!m_Compact || !var.toString().isEmpty()) {
|
||||
result.append(var.toString());
|
||||
}
|
||||
|
||||
+5
-5
@@ -62,7 +62,7 @@ static bool helperExec(LPCWSTR moDirectory, LPCWSTR commandLine)
|
||||
}
|
||||
|
||||
|
||||
bool init(const std::wstring &moDirectory)
|
||||
bool init(const std::wstring &moPath, const std::wstring &dataPath)
|
||||
{
|
||||
DWORD userNameLen = UNLEN + 1;
|
||||
wchar_t userName[UNLEN + 1];
|
||||
@@ -74,22 +74,22 @@ bool init(const std::wstring &moDirectory)
|
||||
wchar_t *commandLine = new wchar_t[32768];
|
||||
|
||||
_snwprintf(commandLine, 32768, L"init \"%ls\" \"%ls\"",
|
||||
moDirectory.c_str(), userName);
|
||||
dataPath.c_str(), userName);
|
||||
|
||||
bool res = helperExec(moDirectory.c_str(), commandLine);
|
||||
bool res = helperExec(moPath.c_str(), commandLine);
|
||||
delete [] commandLine;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool backdateBSAs(const std::wstring &moDirectory, const std::wstring &dataPath)
|
||||
bool backdateBSAs(const std::wstring &moPath, const std::wstring &dataPath)
|
||||
{
|
||||
wchar_t *commandLine = new wchar_t[32768];
|
||||
_snwprintf(commandLine, 32768, L"backdateBSA \"%ls\"",
|
||||
dataPath.c_str());
|
||||
|
||||
bool res = helperExec(moDirectory.c_str(), commandLine);
|
||||
bool res = helperExec(moPath.c_str(), commandLine);
|
||||
delete [] commandLine;
|
||||
|
||||
return res;
|
||||
|
||||
+4
-4
@@ -38,17 +38,17 @@ namespace Helper {
|
||||
* This will create all required sub-directories and give the user running ModOrganizer
|
||||
* write-access
|
||||
*
|
||||
* @param moDirectory absolute path to the ModOrganizer base directory
|
||||
* @param moPath absolute path to the ModOrganizer base directory
|
||||
* @return true on success
|
||||
**/
|
||||
bool init(const std::wstring &moDirectory);
|
||||
bool init(const std::wstring &moPath, const std::wstring &dataPath);
|
||||
|
||||
/**
|
||||
* @brief sets the last modified time for all .bsa-files in the target directory well into the past
|
||||
* @param moDirectory absolute path to the modOrganizer base directory
|
||||
* @param moPath absolute path to the modOrganizer base directory
|
||||
* @param dataPath the path taht contains the .bsa-files, usually the data directory of the game
|
||||
**/
|
||||
bool backdateBSAs(const std::wstring &moDirectory, const std::wstring &dataPath);
|
||||
bool backdateBSAs(const std::wstring &moPath, const std::wstring &dataPath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QDateTime>
|
||||
#include <QDirIterator>
|
||||
#include <QDebug>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include <Shellapi.h>
|
||||
|
||||
@@ -669,7 +670,9 @@ bool InstallationManager::install(const QString &fileName,
|
||||
if (QFile(metaName).exists()) {
|
||||
QSettings metaFile(metaName, QSettings::IniFormat);
|
||||
modID = metaFile.value("modID", 0).toInt();
|
||||
modName.update(metaFile.value("name", "").toString(), GUESS_FALLBACK);
|
||||
QTextDocument doc;
|
||||
doc.setHtml(metaFile.value("name", "").toString());
|
||||
modName.update(doc.toPlainText(), GUESS_FALLBACK);
|
||||
modName.update(metaFile.value("modName", "").toString(), GUESS_META);
|
||||
|
||||
version = metaFile.value("version", "").toString();
|
||||
@@ -688,12 +691,13 @@ bool InstallationManager::install(const QString &fileName,
|
||||
{ // guess the mod name and mod if from the file name if there was no meta information
|
||||
QString guessedModName;
|
||||
int guessedModID = modID;
|
||||
NexusInterface::interpretNexusFileName(QFileInfo(fileName).baseName(), guessedModName, guessedModID, false);
|
||||
NexusInterface::interpretNexusFileName(QFileInfo(fileName).fileName(), guessedModName, guessedModID, false);
|
||||
if ((modID == 0) && (guessedModID != -1)) {
|
||||
modID = guessedModID;
|
||||
} else if (modID != guessedModID) {
|
||||
qDebug("passed mod id: %d, guessed id: %d", modID, guessedModID);
|
||||
}
|
||||
|
||||
modName.update(guessedModName, GUESS_GOOD);
|
||||
}
|
||||
|
||||
|
||||
+52
-52
@@ -27,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QStandardPaths>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
static const char COMPANY_NAME[] = "Tannin";
|
||||
@@ -40,6 +41,11 @@ InstanceManager::InstanceManager()
|
||||
{
|
||||
}
|
||||
|
||||
InstanceManager &InstanceManager::instance()
|
||||
{
|
||||
static InstanceManager s_Instance;
|
||||
return s_Instance;
|
||||
}
|
||||
|
||||
QString InstanceManager::currentInstance() const
|
||||
{
|
||||
@@ -49,6 +55,7 @@ QString InstanceManager::currentInstance() const
|
||||
void InstanceManager::clearCurrentInstance()
|
||||
{
|
||||
setCurrentInstance("");
|
||||
m_Reset = true;
|
||||
}
|
||||
|
||||
void InstanceManager::setCurrentInstance(const QString &name)
|
||||
@@ -81,26 +88,51 @@ QString InstanceManager::queryInstanceName() const
|
||||
|
||||
QString InstanceManager::chooseInstance(const QStringList &instanceList) const
|
||||
{
|
||||
SelectionDialog selection(QObject::tr("Choose Instance"), nullptr);
|
||||
enum class Special : uint8_t {
|
||||
NewInstance,
|
||||
Portable
|
||||
};
|
||||
|
||||
SelectionDialog selection(
|
||||
QString("<h3>%1</h3><br>%2")
|
||||
.arg(QObject::tr("Choose Instance"))
|
||||
.arg(QObject::tr(
|
||||
"Each Instance is a full set of MO data files (mods, "
|
||||
"downloads, profiles, configuration, ...). Use multiple "
|
||||
"instances for different games. If your MO folder is "
|
||||
"writable, you can also store a single instance locally (called "
|
||||
"a portable install).")),
|
||||
nullptr);
|
||||
selection.disableCancel();
|
||||
for (const QString &instance : instanceList) {
|
||||
selection.addChoice(instance, "", instance);
|
||||
}
|
||||
|
||||
selection.addChoice(QObject::tr("New"),
|
||||
selection.addChoice(QIcon(":/MO/gui/add"), QObject::tr("New"),
|
||||
QObject::tr("Create a new instance."),
|
||||
"");
|
||||
static_cast<uint8_t>(Special::NewInstance));
|
||||
|
||||
if (QFileInfo(qApp->applicationDirPath()).isWritable()) {
|
||||
selection.addChoice(QIcon(":/MO/gui/package"), QObject::tr("Portable"),
|
||||
QObject::tr("Use MO folder for data."),
|
||||
static_cast<uint8_t>(Special::Portable));
|
||||
}
|
||||
|
||||
if (selection.exec() == QDialog::Rejected) {
|
||||
qDebug("rejected");
|
||||
throw MOBase::MyException(QObject::tr("Canceled"));
|
||||
}
|
||||
|
||||
QString choice = selection.getChoiceData().toString();
|
||||
QVariant choice = selection.getChoiceData();
|
||||
|
||||
if (choice.isEmpty()) {
|
||||
return queryInstanceName();
|
||||
if (choice.type() == QVariant::String) {
|
||||
return choice.toString();
|
||||
} else {
|
||||
return choice;
|
||||
switch (choice.value<uint8_t>()) {
|
||||
case Special::NewInstance: return queryInstanceName();
|
||||
case Special::Portable: return QString();
|
||||
default: throw std::runtime_error("invalid selection");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,27 +157,6 @@ bool InstanceManager::portableInstall() const
|
||||
}
|
||||
|
||||
|
||||
InstanceManager::InstallationMode InstanceManager::queryInstallMode() const
|
||||
{
|
||||
SelectionDialog selection(QObject::tr("Installation Mode"), nullptr);
|
||||
selection.disableCancel();
|
||||
selection.addChoice(QObject::tr("Portable"),
|
||||
QObject::tr("Everything in one directory, only one game per installation."),
|
||||
0);
|
||||
selection.addChoice(QObject::tr("Regular"),
|
||||
QObject::tr("Data in separate directory, multiple games supported."),
|
||||
1);
|
||||
if (selection.exec() == QDialog::Rejected) {
|
||||
throw MOBase::MyException(QObject::tr("Canceled"));
|
||||
}
|
||||
|
||||
switch (selection.getChoiceData().toInt()) {
|
||||
case 0: return InstallationMode::PORTABLE;
|
||||
default: return InstallationMode::REGULAR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InstanceManager::createDataPath(const QString &dataPath) const
|
||||
{
|
||||
if (!QDir(dataPath).exists()) {
|
||||
@@ -166,41 +177,30 @@ void InstanceManager::createDataPath(const QString &dataPath) const
|
||||
QString InstanceManager::determineDataPath()
|
||||
{
|
||||
QString instanceId = currentInstance();
|
||||
if (instanceId.isEmpty() && portableInstall() && !m_Reset) {
|
||||
// startup, apparently using portable mode before
|
||||
return qApp->applicationDirPath();
|
||||
}
|
||||
|
||||
if (instanceId.isEmpty() && !portableInstall()) {
|
||||
// no portable install and no selected instance
|
||||
QString dataPath = QDir::fromNativeSeparators(
|
||||
QStandardPaths::writableLocation(QStandardPaths::DataLocation)
|
||||
+ "/" + instanceId);
|
||||
|
||||
QStringList instanceList = instances();
|
||||
|
||||
if (instanceList.size() == 0) {
|
||||
if (QFileInfo(qApp->applicationDirPath()).isWritable()) {
|
||||
switch (queryInstallMode()) {
|
||||
case InstallationMode::PORTABLE: {
|
||||
instanceId = QString();
|
||||
} break;
|
||||
case InstallationMode::REGULAR: {
|
||||
instanceId = queryInstanceName();
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
instanceId = queryInstanceName();
|
||||
}
|
||||
} else {
|
||||
// don't offer portable instance if we can't set one up.
|
||||
instanceId = chooseInstance(instanceList);
|
||||
if (instanceId.isEmpty() || !QFileInfo::exists(dataPath)) {
|
||||
instanceId = chooseInstance(instances());
|
||||
if (!instanceId.isEmpty()) {
|
||||
dataPath = QDir::fromNativeSeparators(
|
||||
QStandardPaths::writableLocation(QStandardPaths::DataLocation)
|
||||
+ "/" + instanceId);
|
||||
}
|
||||
}
|
||||
|
||||
if (instanceId.isEmpty()) {
|
||||
qDebug("portable mode");
|
||||
return qApp->applicationDirPath();
|
||||
} else {
|
||||
setCurrentInstance(instanceId);
|
||||
|
||||
QString dataPath = QDir::fromNativeSeparators(
|
||||
QStandardPaths::writableLocation(QStandardPaths::DataLocation)
|
||||
+ "/" + instanceId);
|
||||
|
||||
createDataPath(dataPath);
|
||||
|
||||
return dataPath;
|
||||
|
||||
@@ -27,25 +27,21 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class InstanceManager {
|
||||
|
||||
enum class InstallationMode {
|
||||
PORTABLE,
|
||||
REGULAR
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
InstanceManager();
|
||||
static InstanceManager &instance();
|
||||
|
||||
QString determineDataPath();
|
||||
QStringList instances() const;
|
||||
void clearCurrentInstance();
|
||||
|
||||
private:
|
||||
|
||||
InstanceManager();
|
||||
|
||||
QString currentInstance() const;
|
||||
QString instancePath() const;
|
||||
|
||||
bool portableInstall() const;
|
||||
QStringList instances() const;
|
||||
|
||||
void setCurrentInstance(const QString &name);
|
||||
|
||||
@@ -53,10 +49,11 @@ private:
|
||||
QString chooseInstance(const QStringList &instanceList) const;
|
||||
|
||||
void createDataPath(const QString &dataPath) const;
|
||||
InstallationMode queryInstallMode() const;
|
||||
bool portableInstall() const;
|
||||
|
||||
private:
|
||||
|
||||
QSettings m_AppSettings;
|
||||
bool m_Reset {false};
|
||||
|
||||
};
|
||||
|
||||
+4
-6
@@ -27,7 +27,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <windows.h>
|
||||
#include <DbgHelp.h>
|
||||
|
||||
#include <inject.h>
|
||||
#include <appconfig.h>
|
||||
#include <utility.h>
|
||||
#include <scopeguard.h>
|
||||
@@ -104,7 +103,8 @@ bool createAndMakeWritable(const std::wstring &subPath)
|
||||
"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(dataPath.toStdWString())) {
|
||||
if (!Helper::init(qApp->applicationDirPath().toStdWString(),
|
||||
dataPath.toStdWString())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -533,13 +533,13 @@ int runApplication(MOApplication &application, SingleInstance &instance,
|
||||
// pass the remaining parameters to the binary
|
||||
try {
|
||||
organizer.startApplication(exeName, arguments, QString(), QString());
|
||||
return 0;
|
||||
} catch (const std::exception &e) {
|
||||
reportError(
|
||||
QObject::tr("failed to start application: %1").arg(e.what()));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NexusInterface::instance()->getAccessManager()->startLoginCheck();
|
||||
@@ -630,13 +630,12 @@ int main(int argc, char *argv[])
|
||||
QString dataPath;
|
||||
|
||||
try {
|
||||
dataPath = InstanceManager().determineDataPath();
|
||||
dataPath = InstanceManager::instance().determineDataPath();
|
||||
} catch (const std::exception &e) {
|
||||
QMessageBox::critical(nullptr, QObject::tr("Failed to set up instance"),
|
||||
e.what());
|
||||
return 1;
|
||||
}
|
||||
|
||||
application.setProperty("dataPath", dataPath);
|
||||
|
||||
LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
|
||||
@@ -647,7 +646,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
int result = runApplication(application, instance, splash);
|
||||
|
||||
if (result != INT_MAX) {
|
||||
return result;
|
||||
}
|
||||
|
||||
+71
-51
@@ -37,6 +37,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "savegameinfo.h"
|
||||
#include "spawn.h"
|
||||
#include "versioninfo.h"
|
||||
#include "instancemanager.h"
|
||||
|
||||
#include "report.h"
|
||||
#include "modlist.h"
|
||||
@@ -241,12 +242,14 @@ MainWindow::MainWindow(QSettings &initSettings
|
||||
ui->modList->setItemDelegateForColumn(ModList::COL_FLAGS, new ModFlagIconDelegate(ui->modList));
|
||||
ui->modList->setItemDelegateForColumn(ModList::COL_CONTENT, contentDelegate);
|
||||
ui->modList->header()->installEventFilter(m_OrganizerCore.modList());
|
||||
if (initSettings.contains("mod_list_state")) {
|
||||
ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray());
|
||||
|
||||
bool modListAdjusted = registerWidgetState(ui->modList->objectName(), ui->modList->header(), "mod_list_state");
|
||||
|
||||
if (modListAdjusted) {
|
||||
// hack: force the resize-signal to be triggered because restoreState doesn't seem to do that
|
||||
ui->modList->header()->resizeSection(ModList::COL_CONTENT, ui->modList->header()->sectionSize(ModList::COL_CONTENT) + 1);
|
||||
ui->modList->header()->resizeSection(ModList::COL_CONTENT, ui->modList->header()->sectionSize(ModList::COL_CONTENT) - 1);
|
||||
int sectionSize = ui->modList->header()->sectionSize(ModList::COL_CONTENT);
|
||||
ui->modList->header()->resizeSection(ModList::COL_CONTENT, sectionSize + 1);
|
||||
ui->modList->header()->resizeSection(ModList::COL_CONTENT, sectionSize);
|
||||
} else {
|
||||
// hide these columns by default
|
||||
ui->modList->header()->setSectionHidden(ModList::COL_CONTENT, true);
|
||||
@@ -263,15 +266,17 @@ MainWindow::MainWindow(QSettings &initSettings
|
||||
ui->espList->setModel(m_PluginListSortProxy);
|
||||
ui->espList->sortByColumn(PluginList::COL_PRIORITY, Qt::AscendingOrder);
|
||||
ui->espList->setItemDelegateForColumn(PluginList::COL_FLAGS, new GenericIconDelegate(ui->espList));
|
||||
if (initSettings.contains("plugin_list_state")) {
|
||||
ui->espList->header()->restoreState(initSettings.value("plugin_list_state").toByteArray());
|
||||
}
|
||||
ui->espList->installEventFilter(m_OrganizerCore.pluginList());
|
||||
|
||||
bool pluginListAdjusted = registerWidgetState(ui->espList->objectName(), ui->espList->header(), "plugin_list_state");
|
||||
registerWidgetState(ui->dataTree->objectName(), ui->dataTree->header());
|
||||
registerWidgetState(ui->downloadView->objectName(),
|
||||
ui->downloadView->header());
|
||||
|
||||
ui->splitter->setStretchFactor(0, 3);
|
||||
ui->splitter->setStretchFactor(1, 2);
|
||||
|
||||
resizeLists(initSettings.contains("mod_list_state"), initSettings.contains("plugin_list_state"));
|
||||
resizeLists(modListAdjusted, pluginListAdjusted);
|
||||
|
||||
QMenu *linkMenu = new QMenu(this);
|
||||
linkMenu->addAction(QIcon(":/MO/gui/link"), tr("Toolbar"), this, SLOT(linkToolbar()));
|
||||
@@ -288,7 +293,6 @@ MainWindow::MainWindow(QSettings &initSettings
|
||||
|
||||
// don't allow mouse wheel to switch grouping, too many people accidentally
|
||||
// turn on grouping and then don't understand what happened
|
||||
|
||||
EventFilter *noWheel
|
||||
= new EventFilter(this, [](QObject *, QEvent *event) -> bool {
|
||||
return event->type() == QEvent::Wheel;
|
||||
@@ -1260,7 +1264,6 @@ void MainWindow::refreshDataTree()
|
||||
updateTo(subTree, L"", *m_OrganizerCore.directoryStructure(), conflictsBox->isChecked());
|
||||
tree->insertTopLevelItem(0, subTree);
|
||||
subTree->setExpanded(true);
|
||||
tree->header()->resizeSection(0, 200);
|
||||
}
|
||||
|
||||
|
||||
@@ -1422,12 +1425,7 @@ void MainWindow::readSettings()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::storeSettings(QSettings &settings)
|
||||
{
|
||||
settings.setValue("mod_list_state", ui->modList->header()->saveState());
|
||||
settings.setValue("plugin_list_state", ui->espList->header()->saveState());
|
||||
|
||||
void MainWindow::storeSettings(QSettings &settings) {
|
||||
settings.setValue("group_state", ui->groupCombo->currentIndex());
|
||||
|
||||
settings.setValue("window_geometry", saveGeometry());
|
||||
@@ -1438,7 +1436,13 @@ void MainWindow::storeSettings(QSettings &settings)
|
||||
|
||||
settings.setValue("filters_visible", ui->displayCategoriesBtn->isChecked());
|
||||
|
||||
settings.setValue("selected_executable", ui->executablesListBox->currentIndex());
|
||||
settings.setValue("selected_executable",
|
||||
ui->executablesListBox->currentIndex());
|
||||
|
||||
for (const std::pair<QString, QHeaderView*> kv : m_PersistedGeometry) {
|
||||
QString key = QString("geometry/") + kv.first;
|
||||
settings.setValue(key, kv.second->saveState());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::lock()
|
||||
@@ -2676,31 +2680,6 @@ void MainWindow::replaceCategories_MenuHandler() {
|
||||
refreshFilters();
|
||||
}
|
||||
|
||||
void MainWindow::savePrimaryCategory()
|
||||
{
|
||||
QMenu *menu = qobject_cast<QMenu*>(sender());
|
||||
if (menu == nullptr) {
|
||||
qCritical("not a menu?");
|
||||
return;
|
||||
}
|
||||
|
||||
for (QAction* action : menu->actions()) {
|
||||
QWidgetAction *widgetAction = qobject_cast<QWidgetAction*>(action);
|
||||
if (widgetAction != nullptr) {
|
||||
QRadioButton *btn = qobject_cast<QRadioButton*>(widgetAction->defaultWidget());
|
||||
if (btn->isChecked()) {
|
||||
QModelIndexList selected = ui->modList->selectionModel()->selectedRows();
|
||||
for (int i = 0; i < selected.size(); ++i) {
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ModListSortProxy->mapToSource(selected.at(i)).row());
|
||||
modInfo->setPrimaryCategory(widgetAction->data().toInt());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::checkModsForUpdates()
|
||||
{
|
||||
statusBar()->show();
|
||||
@@ -2760,15 +2739,21 @@ void MainWindow::unignoreUpdate()
|
||||
info->ignoreUpdate(false);
|
||||
}
|
||||
|
||||
void MainWindow::addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInfo::Ptr info)
|
||||
{
|
||||
void MainWindow::addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu,
|
||||
ModInfo::Ptr info) {
|
||||
const std::set<int> &categories = info->getCategories();
|
||||
for (int categoryID : categories) {
|
||||
int catIdx = m_CategoryFactory.getCategoryIndex(categoryID);
|
||||
QWidgetAction *action = new QWidgetAction(primaryCategoryMenu);
|
||||
try {
|
||||
QRadioButton *categoryBox = new QRadioButton(m_CategoryFactory.getCategoryName(catIdx).replace('&', "&&"),
|
||||
primaryCategoryMenu);
|
||||
QRadioButton *categoryBox = new QRadioButton(
|
||||
m_CategoryFactory.getCategoryName(catIdx).replace('&', "&&"),
|
||||
primaryCategoryMenu);
|
||||
connect(categoryBox, &QRadioButton::toggled, [info, categoryID](bool enable) {
|
||||
if (enable) {
|
||||
info->setPrimaryCategory(categoryID);
|
||||
}
|
||||
});
|
||||
categoryBox->setChecked(categoryID == info->getPrimaryCategory());
|
||||
action->setDefaultWidget(categoryBox);
|
||||
} catch (const std::exception &e) {
|
||||
@@ -2932,7 +2917,6 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
|
||||
|
||||
QMenu *primaryCategoryMenu = new QMenu(tr("Primary Category"));
|
||||
connect(primaryCategoryMenu, SIGNAL(aboutToShow()), this, SLOT(addPrimaryCategoryCandidates()));
|
||||
connect(primaryCategoryMenu, SIGNAL(aboutToHide()), this, SLOT(savePrimaryCategory()));
|
||||
addMenuAsPushButton(menu, primaryCategoryMenu);
|
||||
|
||||
menu->addSeparator();
|
||||
@@ -3069,6 +3053,7 @@ void MainWindow::deleteSavegame_clicked()
|
||||
.arg(savesMsgLabel),
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
shellDelete(deleteFiles, true); // recycle bin delete.
|
||||
refreshSaveList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3237,6 +3222,8 @@ void MainWindow::on_actionSettings_triggered()
|
||||
NexusInterface::instance()->setNMMVersion(m_OrganizerCore.settings().getNMMVersion());
|
||||
|
||||
updateDownloadListDelegate();
|
||||
|
||||
m_OrganizerCore.setLogLevel(m_OrganizerCore.settings().logLevel());
|
||||
}
|
||||
|
||||
|
||||
@@ -3902,6 +3889,17 @@ void MainWindow::on_actionProblems_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionChange_Game_triggered()
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Are you sure?"),
|
||||
tr("This will restart MO, continue?"),
|
||||
QMessageBox::Yes | QMessageBox::Cancel)
|
||||
== QMessageBox::Yes) {
|
||||
InstanceManager::instance().clearCurrentInstance();
|
||||
qApp->exit(INT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setCategoryListVisible(bool visible)
|
||||
{
|
||||
if (visible) {
|
||||
@@ -4339,10 +4337,7 @@ void MainWindow::on_bossButton_clicked()
|
||||
QFile::remove(m_OrganizerCore.currentProfile()->getLoadOrderFileName());
|
||||
}
|
||||
m_OrganizerCore.refreshESPList();
|
||||
if (m_OrganizerCore.managedGame()->loadOrderMechanism() == IPluginGame::LoadOrderMechanism::FileTime) {
|
||||
// the load order should have been retrieved from file time, now save it to our own format
|
||||
m_OrganizerCore.savePluginList();
|
||||
}
|
||||
m_OrganizerCore.savePluginList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4557,6 +4552,31 @@ void MainWindow::dropLocalFile(const QUrl &url, const QString &outputDir, bool m
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::registerWidgetState(const QString &name, QHeaderView *view, const char *oldSettingName) {
|
||||
// register the view so it's geometry gets saved at exit
|
||||
m_PersistedGeometry.push_back(std::make_pair(name, view));
|
||||
|
||||
// also, restore the geometry if it was saved before
|
||||
QSettings &settings = m_OrganizerCore.settings().directInterface();
|
||||
|
||||
QString key = QString("geometry/%1").arg(name);
|
||||
QByteArray data;
|
||||
|
||||
if ((oldSettingName != nullptr) && settings.contains(oldSettingName)) {
|
||||
data = settings.value(oldSettingName).toByteArray();
|
||||
settings.remove(oldSettingName);
|
||||
} else if (settings.contains(key)) {
|
||||
data = settings.value(key).toByteArray();
|
||||
}
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
view->restoreState(data);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::dropEvent(QDropEvent *event)
|
||||
{
|
||||
Qt::DropAction action = event->proposedAction();
|
||||
|
||||
+8
-1
@@ -60,6 +60,7 @@ namespace MOShared { class DirectoryEntry; }
|
||||
#include <QStringList>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include <QHeaderView>
|
||||
#include <QVariant>
|
||||
#include <Qt>
|
||||
|
||||
@@ -183,6 +184,9 @@ protected:
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event);
|
||||
virtual void dropEvent(QDropEvent *event);
|
||||
|
||||
private slots:
|
||||
void on_actionChange_Game_triggered();
|
||||
|
||||
private slots:
|
||||
void on_clickBlankButton_clicked();
|
||||
|
||||
@@ -281,6 +285,8 @@ private:
|
||||
|
||||
void dropLocalFile(const QUrl &url, const QString &outputDir, bool move);
|
||||
|
||||
bool registerWidgetState(const QString &name, QHeaderView *view, const char *oldSettingName = nullptr);
|
||||
|
||||
private:
|
||||
|
||||
static const char *PATTERN_BACKUP_GLOB;
|
||||
@@ -345,6 +351,8 @@ private:
|
||||
|
||||
LockedDialog *m_LockDialog { nullptr };
|
||||
|
||||
std::vector<std::pair<QString, QHeaderView*>> m_PersistedGeometry;
|
||||
|
||||
enum class ShortcutType {
|
||||
Toolbar,
|
||||
Desktop,
|
||||
@@ -430,7 +438,6 @@ private slots:
|
||||
void addRemoveCategories_MenuHandler();
|
||||
void replaceCategories_MenuHandler();
|
||||
|
||||
void savePrimaryCategory();
|
||||
void addPrimaryCategoryCandidates();
|
||||
|
||||
void modDetailsUpdated(bool success);
|
||||
|
||||
@@ -1197,6 +1197,7 @@ p, li { white-space: pre-wrap; }
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionChange_Game"/>
|
||||
<addaction name="actionInstallMod"/>
|
||||
<addaction name="actionNexus"/>
|
||||
<addaction name="actionAdd_Profile"/>
|
||||
@@ -1383,6 +1384,18 @@ Right now this has very limited functionality</string>
|
||||
<string>Ctrl+C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChange_Game">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/app_icon</normaloff>:/MO/gui/app_icon</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Change Game</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Open the game selection dialog</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
||||
@@ -129,18 +129,9 @@ bool MOApplication::notify(QObject *receiver, QEvent *event)
|
||||
|
||||
void MOApplication::updateStyle(const QString &fileName)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
if (fileName == "Fusion") {
|
||||
setStyle(QStyleFactory::create("fusion"));
|
||||
setStyleSheet("");
|
||||
#else
|
||||
if (fileName == "Plastique") {
|
||||
setStyle(new ProxyStyle(new QPlastiqueStyle));
|
||||
setStyleSheet("");
|
||||
} else if (fileName == "Cleanlooks") {
|
||||
setStyle(new ProxyStyle(new QCleanlooksStyle));
|
||||
setStyleSheet("");
|
||||
#endif
|
||||
} else {
|
||||
setStyle(new ProxyStyle(QStyleFactory::create(m_DefaultStyle)));
|
||||
if (QFile::exists(fileName)) {
|
||||
|
||||
@@ -12,8 +12,7 @@ ModFlagIconDelegate::ModFlagIconDelegate(QObject *parent)
|
||||
{
|
||||
}
|
||||
|
||||
QList<QString> ModFlagIconDelegate::getIcons(const QModelIndex &index) const
|
||||
{
|
||||
QList<QString> ModFlagIconDelegate::getIcons(const QModelIndex &index) const {
|
||||
QList<QString> result;
|
||||
QVariant modid = index.data(Qt::UserRole + 1);
|
||||
if (modid.isValid()) {
|
||||
@@ -21,7 +20,8 @@ QList<QString> ModFlagIconDelegate::getIcons(const QModelIndex &index) const
|
||||
std::vector<ModInfo::EFlag> flags = info->getFlags();
|
||||
|
||||
{ // insert conflict icon first to provide nicer alignment
|
||||
auto iter = std::find_first_of(flags.begin(), flags.end(), m_ConflictFlags, m_ConflictFlags + 4);
|
||||
auto iter = std::find_first_of(flags.begin(), flags.end(),
|
||||
m_ConflictFlags, m_ConflictFlags + 4);
|
||||
if (iter != flags.end()) {
|
||||
result.append(getFlagIcon(*iter));
|
||||
flags.erase(iter);
|
||||
|
||||
+14
-27
@@ -35,6 +35,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <versioninfo.h>
|
||||
#include <appconfig.h>
|
||||
#include <scriptextender.h>
|
||||
#include <unmanagedmods.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDirIterator>
|
||||
@@ -75,11 +76,13 @@ ModInfo::Ptr ModInfo::createFrom(const QDir &dir, DirectoryEntry **directoryStru
|
||||
return result;
|
||||
}
|
||||
|
||||
ModInfo::Ptr ModInfo::createFromPlugin(const QString &espName, const QStringList &bsaNames
|
||||
, DirectoryEntry ** directoryStructure)
|
||||
{
|
||||
ModInfo::Ptr ModInfo::createFromPlugin(const QString &modName,
|
||||
const QString &espName,
|
||||
const QStringList &bsaNames,
|
||||
DirectoryEntry **directoryStructure) {
|
||||
QMutexLocker locker(&s_Mutex);
|
||||
ModInfo::Ptr result = ModInfo::Ptr(new ModInfoForeign(espName, bsaNames, directoryStructure));
|
||||
ModInfo::Ptr result = ModInfo::Ptr(
|
||||
new ModInfoForeign(modName, espName, bsaNames, directoryStructure));
|
||||
s_Collection.push_back(result);
|
||||
return result;
|
||||
}
|
||||
@@ -92,12 +95,10 @@ QString ModInfo::getContentTypeName(int contentType)
|
||||
case CONTENT_MESH: return tr("Meshes");
|
||||
case CONTENT_BSA: return tr("BSA");
|
||||
case CONTENT_INTERFACE: return tr("UI Changes");
|
||||
case CONTENT_MUSIC: return tr("Music");
|
||||
case CONTENT_SOUND: return tr("Sound Effects");
|
||||
case CONTENT_SCRIPT: return tr("Scripts");
|
||||
case CONTENT_SKSE: return tr("SKSE Plugins");
|
||||
case CONTENT_SKYPROC: return tr("SkyProc Tools");
|
||||
case CONTENT_STRING: return tr("Strings");
|
||||
default: throw MyException(tr("invalid content type %1").arg(contentType));
|
||||
}
|
||||
}
|
||||
@@ -219,27 +220,13 @@ void ModInfo::updateFromDisc(const QString &modDirectory,
|
||||
}
|
||||
}
|
||||
|
||||
{ // list plugins in the data directory and make a foreign-managed mod out of each
|
||||
QStringList dlcPlugins = game->DLCPlugins();
|
||||
QStringList mainPlugins = game->primaryPlugins();
|
||||
QDir dataDir(game->dataDirectory());
|
||||
for (const QString &file : dataDir.entryList({ "*.esp", "*.esm" })) {
|
||||
if (std::find_if(mainPlugins.begin(), mainPlugins.end(),
|
||||
[&file](QString const &p) {
|
||||
return p.compare(file, Qt::CaseInsensitive) == 0; }) == mainPlugins.end()
|
||||
&& (displayForeign // show non-dlc bundles only if the user wants them
|
||||
|| std::find_if(dlcPlugins.begin(), dlcPlugins.end(),
|
||||
[&file](QString const &p) {
|
||||
return p.compare(file, Qt::CaseInsensitive) == 0; }) != dlcPlugins.end())) {
|
||||
|
||||
QFileInfo f(file); //Just so I can get a basename...
|
||||
QStringList archives;
|
||||
for (const QString &archiveName : dataDir.entryList({ f.baseName() + "*.bsa" })) {
|
||||
archives.append(dataDir.absoluteFilePath(archiveName));
|
||||
}
|
||||
|
||||
createFromPlugin(file, archives, directoryStructure);
|
||||
}
|
||||
UnmanagedMods *unmanaged = game->feature<UnmanagedMods>();
|
||||
if (unmanaged != nullptr) {
|
||||
for (const QString &modName : unmanaged->mods(!displayForeign)) {
|
||||
createFromPlugin(unmanaged->displayName(modName),
|
||||
unmanaged->referenceFile(modName).absoluteFilePath(),
|
||||
unmanaged->secondaryFiles(modName),
|
||||
directoryStructure);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user