mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2a7c7c223 | ||
|
|
7b4582c1b1 | ||
|
|
5d7b23acef | ||
|
|
3628ec930b | ||
|
|
e22aeca3ff | ||
|
|
cbd6b288eb | ||
|
|
484749e612 | ||
|
|
5b3cdaa83b | ||
|
|
6d3f88b330 |
@@ -18,5 +18,18 @@ staging_prepare/*
|
||||
staging_trans/*
|
||||
tools/python_zip/*
|
||||
Makefile
|
||||
html
|
||||
*.vcxproj
|
||||
*.pdb
|
||||
*.dll
|
||||
*.exp
|
||||
*.tlog
|
||||
*.user
|
||||
*.obj
|
||||
*.suo
|
||||
*.sln
|
||||
*.log
|
||||
*.filters
|
||||
*.lib
|
||||
syntax: regexp
|
||||
Makefile\.(Debug|Release)
|
||||
|
||||
@@ -43,7 +43,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
BrowserDialog::BrowserDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::BrowserDialog)
|
||||
, m_AccessManager(new QNetworkAccessManager)
|
||||
, m_AccessManager(new QNetworkAccessManager(this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ public:
|
||||
static const int CATEGORY_SPECIAL_NOCATEGORY = 10003;
|
||||
static const int CATEGORY_SPECIAL_CONFLICT = 10004;
|
||||
static const int CATEGORY_SPECIAL_NOTENDORSED = 10005;
|
||||
static const int CATEGORY_SPECIAL_MANAGED = 10006;
|
||||
static const int CATEGORY_SPECIAL_UNMANAGED = 10007;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
+26
-27
@@ -63,7 +63,6 @@ void DirectoryRefresher::setMods(const std::vector<std::tuple<QString, QString,
|
||||
m_EnabledArchives = managedArchives;
|
||||
}
|
||||
|
||||
|
||||
void DirectoryRefresher::cleanStructure(DirectoryEntry *structure)
|
||||
{
|
||||
static wchar_t *files[] = { L"meta.ini", L"readme.txt" };
|
||||
@@ -77,21 +76,27 @@ void DirectoryRefresher::cleanStructure(DirectoryEntry *structure)
|
||||
}
|
||||
}
|
||||
|
||||
void DirectoryRefresher::addModToStructure(DirectoryEntry *directoryStructure
|
||||
, const QString &modName
|
||||
, int priority
|
||||
, const QString &directory
|
||||
, const QStringList &stealFiles
|
||||
, const QStringList &archives)
|
||||
void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &archives)
|
||||
{
|
||||
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
|
||||
std::wstring modNameW = ToWString(modName);
|
||||
|
||||
foreach (const QString &archive, archives) {
|
||||
QFileInfo fileInfo(archive);
|
||||
if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) {
|
||||
directoryStructure->addFromBSA(ToWString(modName), directoryW,
|
||||
ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DirectoryRefresher::addModFilesToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &stealFiles)
|
||||
{
|
||||
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
|
||||
|
||||
if (stealFiles.length() > 0) {
|
||||
// instead of adding all the files of the target directory, we just change the root of the specified
|
||||
// files to this mod
|
||||
directoryStructure->createOrigin(modNameW, directoryW, priority);
|
||||
FilesOrigin origin = directoryStructure->createOrigin(ToWString(modName), directoryW, priority);
|
||||
foreach (const QString &filename, stealFiles) {
|
||||
QFileInfo fileInfo(filename);
|
||||
FileEntry::Ptr file = directoryStructure->findFile(ToWString(fileInfo.fileName()));
|
||||
@@ -99,30 +104,24 @@ void DirectoryRefresher::addModToStructure(DirectoryEntry *directoryStructure
|
||||
if (file->getOrigin() == 0) {
|
||||
// replace data as the origin on this bsa
|
||||
file->removeOrigin(0);
|
||||
file->addOrigin(directoryStructure->getOriginByName(modNameW).getID(),
|
||||
file->getFileTime(), L"");
|
||||
file->addOrigin(origin.getID(), file->getFileTime(), L"");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
directoryStructure->addFromOrigin(modNameW, directoryW, priority);
|
||||
directoryStructure->addFromOrigin(ToWString(modName), directoryW, priority);
|
||||
}
|
||||
/* QDir dir(directory);
|
||||
QFileInfoList bsaFiles = dir.entryInfoList(QStringList("*.bsa"), QDir::Files);
|
||||
foreach (QFileInfo file, bsaFiles) {
|
||||
if (m_EnabledArchives.find(file.fileName()) != m_EnabledArchives.end()) {
|
||||
directoryStructure->addFromBSA(ToWString(modName), directoryW,
|
||||
ToWString(QDir::toNativeSeparators(file.absoluteFilePath())), priority);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
foreach (const QString &archive, archives) {
|
||||
QFileInfo fileInfo(archive);
|
||||
if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) {
|
||||
directoryStructure->addFromBSA(modNameW, directoryW,
|
||||
ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority);
|
||||
}
|
||||
}
|
||||
void DirectoryRefresher::addModToStructure(DirectoryEntry *directoryStructure
|
||||
, const QString &modName
|
||||
, int priority
|
||||
, const QString &directory
|
||||
, const QStringList &stealFiles
|
||||
, const QStringList &archives)
|
||||
{
|
||||
addModFilesToStructure(directoryStructure, modName, priority, directory, stealFiles);
|
||||
addModBSAToStructure(directoryStructure, modName, priority, directory, archives);
|
||||
}
|
||||
|
||||
void DirectoryRefresher::refresh()
|
||||
|
||||
@@ -79,13 +79,35 @@ public:
|
||||
|
||||
/**
|
||||
* @brief add files for a mod to the directory structure, including bsas
|
||||
* @param directoryStructure
|
||||
* @param modName
|
||||
* @param priorityBSA
|
||||
* @param priority
|
||||
* @param directory
|
||||
* @param priorityDir
|
||||
* @param stealFiles
|
||||
* @param archives
|
||||
*/
|
||||
void addModToStructure(MOShared::DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &stealFiles, const QStringList &archives);
|
||||
|
||||
/**
|
||||
* @brief add only the bsas of a mod to the directory structure
|
||||
* @param directoryStructure
|
||||
* @param modName
|
||||
* @param priority
|
||||
* @param directory
|
||||
* @param archives
|
||||
*/
|
||||
void addModBSAToStructure(MOShared::DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &archives);
|
||||
|
||||
/**
|
||||
* @brief add only regular files ofr a mod to the directory structure
|
||||
* @param directoryStructure
|
||||
* @param modName
|
||||
* @param priority
|
||||
* @param directory
|
||||
* @param stealFiles
|
||||
*/
|
||||
void addModFilesToStructure(MOShared::DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &stealFiles);
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
|
||||
@@ -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="icuin49.dll"/>
|
||||
<file name="icuuc49.dll"/>
|
||||
<file name="icudt49.dll"/>
|
||||
<file name="icuin52.dll"/>
|
||||
<file name="icuuc52.dll"/>
|
||||
<file name="icudt52.dll"/>
|
||||
<file name="Qt5Core.dll"/>
|
||||
<file name="Qt5Declarative.dll"/>
|
||||
<file name="Qt5Gui.dll"/>
|
||||
@@ -14,4 +14,4 @@
|
||||
<file name="Qt5Widgets.dll"/>
|
||||
<file name="Qt5Xml.dll"/>
|
||||
<file name="Qt5XmlPatterns.dll"/>
|
||||
</assembly>
|
||||
</assembly>
|
||||
@@ -350,9 +350,6 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const ModRepositoryFileI
|
||||
bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName,
|
||||
int modID, int fileID, const ModRepositoryFileInfo *fileInfo)
|
||||
{
|
||||
if (!reply->isRunning()) {
|
||||
qDebug("this is not a running download! %d", reply->isFinished());
|
||||
}
|
||||
// download invoked from an already open network reply (i.e. download link in the browser)
|
||||
DownloadInfo *newDownload = DownloadInfo::createNew(fileInfo, URLs);
|
||||
|
||||
@@ -401,6 +398,7 @@ void DownloadManager::removePending(int modID, int fileID)
|
||||
|
||||
void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownload, bool resume)
|
||||
{
|
||||
reply->setReadBufferSize(1024 * 1024); // don't read more than 1MB at once to avoid memory troubles
|
||||
newDownload->m_Reply = reply;
|
||||
setState(newDownload, STATE_DOWNLOADING);
|
||||
if (newDownload->m_Urls.count() == 0) {
|
||||
@@ -1339,8 +1337,11 @@ void DownloadManager::downloadFinished()
|
||||
DownloadInfo *info = findDownload(this->sender(), &index);
|
||||
if (info != NULL) {
|
||||
QNetworkReply *reply = info->m_Reply;
|
||||
QByteArray data = info->m_Reply->readAll();
|
||||
info->m_Output.write(data);
|
||||
QByteArray data;
|
||||
if (reply->isOpen()) {
|
||||
data = reply->readAll();
|
||||
info->m_Output.write(data);
|
||||
}
|
||||
info->m_Output.close();
|
||||
TaskProgressManager::instance().forgetMe(info->m_TaskProgressId);
|
||||
|
||||
|
||||
+81
-68
@@ -320,6 +320,9 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
m_CheckBSATimer.setSingleShot(true);
|
||||
connect(&m_CheckBSATimer, SIGNAL(timeout()), this, SLOT(checkBSAList()));
|
||||
|
||||
m_UpdateProblemsTimer.setSingleShot(true);
|
||||
connect(&m_UpdateProblemsTimer, SIGNAL(timeout()), this, SLOT(updateProblemsButton()));
|
||||
|
||||
m_SaveMetaTimer.setSingleShot(false);
|
||||
connect(&m_SaveMetaTimer, SIGNAL(timeout()), this, SLOT(saveModMetas()));
|
||||
m_SaveMetaTimer.start(5000);
|
||||
@@ -530,6 +533,14 @@ void MainWindow::updateToolBar()
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::scheduleUpdateButton()
|
||||
{
|
||||
if (!m_UpdateProblemsTimer.isActive()) {
|
||||
m_UpdateProblemsTimer.start(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::updateProblemsButton()
|
||||
{
|
||||
int numProblems = checkForProblems();
|
||||
@@ -661,7 +672,7 @@ void MainWindow::createHelpWidget()
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::saveArchiveList()
|
||||
bool MainWindow::saveArchiveList()
|
||||
{
|
||||
if (m_ArchivesInit) {
|
||||
SafeWriteFile archiveFile(m_CurrentProfile->getArchivesFileName());
|
||||
@@ -680,10 +691,12 @@ void MainWindow::saveArchiveList()
|
||||
}
|
||||
if (archiveFile.commitIfDifferent(m_ArchiveListHash)) {
|
||||
qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_CurrentProfile->getArchivesFileName())));
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
qWarning("archive list not initialised");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::savePluginList()
|
||||
@@ -1148,7 +1161,7 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName)
|
||||
IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(plugin);
|
||||
if (diagnose != NULL) {
|
||||
m_DiagnosisPlugins.push_back(diagnose);
|
||||
diagnose->onInvalidated([&] () { this->updateProblemsButton(); });
|
||||
diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); });
|
||||
}
|
||||
}
|
||||
{ // mod page plugin
|
||||
@@ -1418,10 +1431,8 @@ void MainWindow::setExecutableIndex(int index)
|
||||
} else {
|
||||
executableBox->setCurrentIndex(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::activateSelectedProfile()
|
||||
{
|
||||
QString profileName = ui->profileBox->currentText();
|
||||
@@ -1440,7 +1451,6 @@ void MainWindow::activateSelectedProfile()
|
||||
refreshModList();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_profileBox_currentIndexChanged(int index)
|
||||
{
|
||||
if (ui->profileBox->isEnabled()) {
|
||||
@@ -1646,8 +1656,6 @@ bool MainWindow::refreshProfiles(bool selectProfile)
|
||||
std::set<QString> MainWindow::enabledArchives()
|
||||
{
|
||||
std::set<QString> result;
|
||||
|
||||
|
||||
QFile archiveFile(m_CurrentProfile->getArchivesFileName());
|
||||
if (archiveFile.open(QIODevice::ReadOnly)) {
|
||||
while (!archiveFile.atEnd()) {
|
||||
@@ -1658,7 +1666,6 @@ std::set<QString> MainWindow::enabledArchives()
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::refreshDirectoryStructure()
|
||||
{
|
||||
m_DirectoryUpdate = true;
|
||||
@@ -1672,7 +1679,6 @@ void MainWindow::refreshDirectoryStructure()
|
||||
QTimer::singleShot(0, &m_DirectoryRefresher, SLOT(refresh()));
|
||||
}
|
||||
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
extern QPixmap qt_pixmapFromWinHICON(HICON icon);
|
||||
#else
|
||||
@@ -1692,7 +1698,6 @@ QIcon MainWindow::iconForExecutable(const QString &filePath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::refreshExecutablesList()
|
||||
{
|
||||
QComboBox* executablesList = findChild<QComboBox*>("executablesListBox");
|
||||
@@ -1806,6 +1811,7 @@ void MainWindow::refreshModList(bool saveChanges)
|
||||
m_CurrentProfile->writeModlistNow(true);
|
||||
}
|
||||
ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
|
||||
|
||||
m_CurrentProfile->refreshModStatus();
|
||||
|
||||
m_ModList.notifyChange(-1);
|
||||
@@ -1969,15 +1975,6 @@ void MainWindow::checkBSAList()
|
||||
item->setIcon(0, QIcon(":/MO/gui/warning"));
|
||||
item->setToolTip(0, tr("This bsa is enabled in the ini file so it may be required!"));
|
||||
modWarning = true;
|
||||
/* } else {
|
||||
QString espName = filename.mid(0, filename.length() - 3).append("esp").toLower();
|
||||
QString esmName = filename.mid(0, filename.length() - 3).append("esm").toLower();
|
||||
if (m_PluginList.isEnabled(espName) || m_PluginList.isEnabled(esmName)) {
|
||||
item->setIcon(0, QIcon(":/MO/gui/warning"));
|
||||
item->setToolTip(0, tr("This archive will still be loaded since there is a plugin of the same name but "
|
||||
"its files will not follow installation order!"));
|
||||
modWarning = true;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2632,7 +2629,6 @@ void MainWindow::directory_refreshed()
|
||||
if (m_CurrentProfile != NULL) {
|
||||
refreshLists();
|
||||
}
|
||||
// m_RefreshProgress->setVisible(false);
|
||||
|
||||
// some problem-reports may rely on the virtual directory tree so they need to be updated
|
||||
// now
|
||||
@@ -2645,7 +2641,6 @@ void MainWindow::directory_refreshed()
|
||||
statusBar()->hide();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::externalMessage(const QString &message)
|
||||
{
|
||||
if (message.left(6).toLower() == "nxm://") {
|
||||
@@ -2654,31 +2649,56 @@ void MainWindow::externalMessage(const QString &message)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo)
|
||||
{
|
||||
// add files of the bsa to the directory structure
|
||||
m_DirectoryRefresher.addModFilesToStructure(m_DirectoryStructure
|
||||
, modInfo->name()
|
||||
, m_CurrentProfile->getModPriority(index)
|
||||
, modInfo->absolutePath()
|
||||
, modInfo->stealFiles()
|
||||
);
|
||||
DirectoryRefresher::cleanStructure(m_DirectoryStructure);
|
||||
// need to refresh plugin list now so we can activate esps
|
||||
refreshESPList();
|
||||
// activate all esps of the specified mod so the bsas get activated along with it
|
||||
updateModActiveState(index, true);
|
||||
// now we need to refresh the bsa list and save it so there is no confusion about what archives are avaiable and active
|
||||
refreshBSAList();
|
||||
saveArchiveList();
|
||||
m_DirectoryRefresher.setMods(m_CurrentProfile->getActiveMods(), enabledArchives());
|
||||
|
||||
// finally also add files from bsas to the directory structure
|
||||
m_DirectoryRefresher.addModBSAToStructure(m_DirectoryStructure
|
||||
, modInfo->name()
|
||||
, m_CurrentProfile->getModPriority(index)
|
||||
, modInfo->absolutePath()
|
||||
, modInfo->archives()
|
||||
);
|
||||
}
|
||||
|
||||
void MainWindow::modStatusChanged(unsigned int index)
|
||||
{
|
||||
try {
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
|
||||
if (m_CurrentProfile->modEnabled(index)) {
|
||||
m_DirectoryRefresher.addModToStructure(m_DirectoryStructure
|
||||
, modInfo->name()
|
||||
, m_CurrentProfile->getModPriority(index)
|
||||
, modInfo->absolutePath()
|
||||
, modInfo->stealFiles()
|
||||
, modInfo->archives());
|
||||
DirectoryRefresher::cleanStructure(m_DirectoryStructure);
|
||||
updateModInDirectoryStructure(index, modInfo);
|
||||
} else {
|
||||
updateModActiveState(index, false);
|
||||
refreshESPList();
|
||||
if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
|
||||
FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name()));
|
||||
origin.enable(false);
|
||||
}
|
||||
}
|
||||
modInfo->clearCaches();
|
||||
|
||||
for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) {
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
|
||||
int priority = m_CurrentProfile->getModPriority(i);
|
||||
if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
|
||||
m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority);
|
||||
// priorities in the directory structure are one higher because data is 0
|
||||
m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority + 1);
|
||||
}
|
||||
}
|
||||
m_DirectoryStructure->getFileRegister()->sortOrigins();
|
||||
@@ -2704,7 +2724,8 @@ void MainWindow::modorder_changed()
|
||||
int priority = m_CurrentProfile->getModPriority(i);
|
||||
if (m_CurrentProfile->modEnabled(i)) {
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
|
||||
m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority);
|
||||
// priorities in the directory structure are one higher because data is 0
|
||||
m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority + 1);
|
||||
}
|
||||
}
|
||||
refreshBSAList();
|
||||
@@ -2723,33 +2744,30 @@ void MainWindow::procFinished(int, QProcess::ExitStatus)
|
||||
this->sender()->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::profileRefresh()
|
||||
{
|
||||
m_CurrentProfile->writeModlist();
|
||||
// have to refresh mods twice (again in refreshModList), otherwise the refresh isn't complete. Not sure why
|
||||
ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
|
||||
m_CurrentProfile->refreshModStatus();
|
||||
|
||||
refreshModList();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::showMessage(const QString &message)
|
||||
{
|
||||
MessageDialog::showMessage(message, this);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::showError(const QString &message)
|
||||
{
|
||||
reportError(message);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::installMod_clicked()
|
||||
{
|
||||
installMod();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::renameModInList(QFile &modList, const QString &oldName, const QString &newName)
|
||||
{
|
||||
//TODO this code needs to be merged with ModList::readFrom
|
||||
@@ -2911,6 +2929,8 @@ void MainWindow::refreshFilters()
|
||||
addFilterItem(NULL, tr("<Checked>"), CategoryFactory::CATEGORY_SPECIAL_CHECKED);
|
||||
addFilterItem(NULL, tr("<Unchecked>"), CategoryFactory::CATEGORY_SPECIAL_UNCHECKED);
|
||||
addFilterItem(NULL, tr("<Update>"), CategoryFactory::CATEGORY_SPECIAL_UPDATEAVAILABLE);
|
||||
addFilterItem(NULL, tr("<Managed by MO>"), CategoryFactory::CATEGORY_SPECIAL_MANAGED);
|
||||
addFilterItem(NULL, tr("<Managed outside MO>"), CategoryFactory::CATEGORY_SPECIAL_UNMANAGED);
|
||||
addFilterItem(NULL, tr("<No category>"), CategoryFactory::CATEGORY_SPECIAL_NOCATEGORY);
|
||||
addFilterItem(NULL, tr("<Conflicted>"), CategoryFactory::CATEGORY_SPECIAL_CONFLICT);
|
||||
addFilterItem(NULL, tr("<Not Endorsed>"), CategoryFactory::CATEGORY_SPECIAL_NOTENDORSED);
|
||||
@@ -2975,37 +2995,34 @@ void MainWindow::restoreBackup_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::modlistChanged(const QModelIndex &index, int role)
|
||||
void MainWindow::updateModActiveState(int index, bool active)
|
||||
{
|
||||
if (role == Qt::CheckStateRole) {
|
||||
if (index.data(Qt::CheckStateRole).toBool()) {
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(index.row());
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
|
||||
|
||||
QDir dir(modInfo->absolutePath());
|
||||
foreach (const QString &esm, dir.entryList(QStringList("*.esm"), QDir::Files)) {
|
||||
m_PluginList.enableESP(esm);
|
||||
}
|
||||
|
||||
int enabled = 0;
|
||||
QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files);
|
||||
foreach (const QString &esp, esps) {
|
||||
if (!m_PluginList.isEnabled(esp)) {
|
||||
m_PluginList.enableESP(esp);
|
||||
++enabled;
|
||||
}
|
||||
}
|
||||
if (enabled > 1) {
|
||||
MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), this);
|
||||
}
|
||||
m_PluginList.refreshLoadOrder();
|
||||
// immediately save affected lists
|
||||
savePluginList();
|
||||
saveArchiveList();
|
||||
QDir dir(modInfo->absolutePath());
|
||||
foreach (const QString &esm, dir.entryList(QStringList("*.esm"), QDir::Files)) {
|
||||
m_PluginList.enableESP(esm, active);
|
||||
}
|
||||
int enabled = 0;
|
||||
QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files);
|
||||
foreach (const QString &esp, esps) {
|
||||
if (active != m_PluginList.isEnabled(esp)) {
|
||||
m_PluginList.enableESP(esp, active);
|
||||
++enabled;
|
||||
}
|
||||
}
|
||||
if (active && (enabled > 1)) {
|
||||
MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), this);
|
||||
}
|
||||
m_PluginList.refreshLoadOrder();
|
||||
// immediately save affected lists
|
||||
savePluginList();
|
||||
// refreshBSAList();
|
||||
}
|
||||
|
||||
void MainWindow::modlistChanged(const QModelIndex&, int)
|
||||
{
|
||||
}
|
||||
|
||||
void MainWindow::removeMod_clicked()
|
||||
{
|
||||
@@ -3162,12 +3179,9 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index,
|
||||
dialog->raise();
|
||||
dialog->activateWindow();
|
||||
connect(dialog, SIGNAL(finished(int)), this, SLOT(overwriteClosed(int)));
|
||||
} else if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_FOREIGN) != flags.end()) {
|
||||
// nop - no menu for this file type
|
||||
return;
|
||||
} else {
|
||||
modInfo->saveMeta();
|
||||
ModInfoDialog dialog(modInfo, m_DirectoryStructure, this);
|
||||
ModInfoDialog dialog(modInfo, m_DirectoryStructure, modInfo->hasFlag(ModInfo::FLAG_FOREIGN), this);
|
||||
connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString)));
|
||||
connect(&dialog, SIGNAL(downloadRequest(QString)), this, SLOT(downloadRequestedNXM(QString)));
|
||||
connect(&dialog, SIGNAL(modOpen(QString, int)), this, SLOT(displayModInformation(QString, int)), Qt::QueuedConnection);
|
||||
@@ -3995,6 +4009,7 @@ void MainWindow::linkToolbar()
|
||||
const Executable &selectedExecutable = ui->executablesListBox->itemData(ui->executablesListBox->currentIndex()).value<Executable>();
|
||||
Executable &exe = m_ExecutablesList.find(selectedExecutable.m_Title);
|
||||
exe.m_Toolbar = !exe.m_Toolbar;
|
||||
ui->linkButton->menu()->actions().at(2)->setIcon(exe.m_Toolbar ? QIcon(":/MO/gui/remove") : QIcon(":/MO/gui/link"));
|
||||
updateToolBar();
|
||||
}
|
||||
|
||||
@@ -4091,8 +4106,7 @@ void MainWindow::on_actionSettings_triggered()
|
||||
|
||||
if ((m_Settings.getModDirectory() != oldModDirectory)
|
||||
|| (m_Settings.displayForeign() != oldDisplayForeign)) {
|
||||
refreshModList();
|
||||
refreshLists();
|
||||
profileRefresh();
|
||||
}
|
||||
|
||||
if (m_Settings.getCacheDirectory() != oldCacheDirectory) {
|
||||
@@ -4244,7 +4258,6 @@ void MainWindow::installDownload(int index)
|
||||
MessageDialog::showMessage(tr("Installation successful"), this);
|
||||
refreshModList();
|
||||
|
||||
|
||||
QModelIndexList posList = m_ModList.match(m_ModList.index(0, 0), Qt::DisplayRole, static_cast<const QString&>(modName));
|
||||
if (posList.count() == 1) {
|
||||
ui->modList->scrollTo(posList.at(0));
|
||||
|
||||
+14
-6
@@ -99,7 +99,6 @@ public:
|
||||
void readSettings();
|
||||
|
||||
bool addProfile();
|
||||
void refreshLists();
|
||||
void refreshBSAList();
|
||||
void refreshDataTree();
|
||||
void refreshSaveList();
|
||||
@@ -127,7 +126,7 @@ public:
|
||||
|
||||
void addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInfo::Ptr info);
|
||||
|
||||
void saveArchiveList();
|
||||
bool saveArchiveList();
|
||||
|
||||
void createStdoutPipe(HANDLE *stdOutRead, HANDLE *stdOutWrite);
|
||||
std::string readFromPipe(HANDLE stdOutRead);
|
||||
@@ -135,8 +134,12 @@ public:
|
||||
|
||||
HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = "");
|
||||
|
||||
void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo);
|
||||
|
||||
public slots:
|
||||
|
||||
void refreshLists();
|
||||
|
||||
void displayColumnSelection(const QPoint &pos);
|
||||
|
||||
void externalMessage(const QString &message);
|
||||
@@ -260,8 +263,6 @@ private:
|
||||
|
||||
void setCategoryListVisible(bool visible);
|
||||
|
||||
void updateProblemsButton();
|
||||
|
||||
SaveGameGamebryo *getSaveGame(const QString &name);
|
||||
SaveGameGamebryo *getSaveGame(QListWidgetItem *item);
|
||||
|
||||
@@ -287,6 +288,10 @@ private:
|
||||
|
||||
std::set<QString> enabledArchives();
|
||||
|
||||
void scheduleUpdateButton();
|
||||
|
||||
void updateModActiveState(int index, bool active);
|
||||
|
||||
private:
|
||||
|
||||
static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1;
|
||||
@@ -356,6 +361,7 @@ private:
|
||||
bool m_ArchivesInit;
|
||||
QTimer m_CheckBSATimer;
|
||||
QTimer m_SaveMetaTimer;
|
||||
QTimer m_UpdateProblemsTimer;
|
||||
|
||||
QTime m_StartTime;
|
||||
SaveGameInfoWidget *m_CurrentSaveView;
|
||||
@@ -478,7 +484,6 @@ private slots:
|
||||
void modlistChanged(int row);
|
||||
|
||||
void nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant userData, QVariant resultData, int requestID);
|
||||
// void nxmEndorsementToggled(int, QVariant, QVariant resultData, int);
|
||||
void nxmDownloadURLs(int modID, int fileID, QVariant userData, QVariant resultData, int requestID);
|
||||
void nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorString);
|
||||
|
||||
@@ -510,6 +515,9 @@ private slots:
|
||||
void startExeAction();
|
||||
|
||||
void checkBSAList();
|
||||
|
||||
void updateProblemsButton();
|
||||
|
||||
void saveModMetas();
|
||||
|
||||
void updateStyle(const QString &style);
|
||||
@@ -551,9 +559,9 @@ private slots:
|
||||
void delayedRemove();
|
||||
|
||||
void requestDownload(const QUrl &url, QNetworkReply *reply);
|
||||
void profileRefresh();
|
||||
|
||||
private slots: // ui slots
|
||||
void profileRefresh();
|
||||
// actions
|
||||
void on_actionAdd_Profile_triggered();
|
||||
void on_actionInstallMod_triggered();
|
||||
|
||||
@@ -81,6 +81,7 @@ void MessageDialog::resizeEvent(QResizeEvent *event)
|
||||
|
||||
void MessageDialog::showMessage(const QString &text, QWidget *reference, bool bringToFront)
|
||||
{
|
||||
qDebug("%s", qPrintable(text));
|
||||
if (reference != NULL) {
|
||||
if (bringToFront || (qApp->activeWindow() != NULL)) {
|
||||
MessageDialog *dialog = new MessageDialog(text, reference);
|
||||
|
||||
+1
-1
@@ -756,7 +756,7 @@ void ModInfoRegular::setNeverEndorse()
|
||||
bool ModInfoRegular::remove()
|
||||
{
|
||||
m_MetaInfoChanged = false;
|
||||
return shellDelete(QStringList(absolutePath()));
|
||||
return shellDelete(QStringList(absolutePath()), true);
|
||||
}
|
||||
|
||||
void ModInfoRegular::endorse(bool doEndorse)
|
||||
|
||||
+122
-109
@@ -60,7 +60,7 @@ bool operator<(const ModFileListWidget &LHS, const ModFileListWidget &RHS)
|
||||
}
|
||||
|
||||
|
||||
ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directory, QWidget *parent)
|
||||
ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directory, bool unmanaged, QWidget *parent)
|
||||
: TutorableDialog("ModInfoDialog", parent), ui(new Ui::ModInfoDialog), m_ModInfo(modInfo),
|
||||
m_ThumbnailMapper(this), m_RequestStarted(false),
|
||||
m_DeleteAction(NULL), m_RenameAction(NULL), m_OpenAction(NULL),
|
||||
@@ -69,54 +69,19 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
|
||||
ui->setupUi(this);
|
||||
this->setWindowTitle(modInfo->name());
|
||||
this->setWindowModality(Qt::WindowModal);
|
||||
m_UTF8Codec = QTextCodec::codecForName("utf-8");
|
||||
|
||||
QListWidget *textFileList = findChild<QListWidget*>("textFileList");
|
||||
QListWidget *iniTweaksList = findChild<QListWidget*>("iniTweaksList");
|
||||
QListWidget *activeESPList = findChild<QListWidget*>("activeESPList");
|
||||
QListWidget *inactiveESPList = findChild<QListWidget*>("inactiveESPList");
|
||||
QTreeWidget *categoriesTree = findChild<QTreeWidget*>("categoriesTree");
|
||||
QHBoxLayout *thumbnailArea = findChild<QHBoxLayout*>("thumbnailArea");
|
||||
|
||||
m_FileTree = findChild<QTreeView*>("fileTree");
|
||||
|
||||
m_RootPath = modInfo->absolutePath();
|
||||
|
||||
QString metaFileName = m_RootPath.mid(0).append("/meta.ini");
|
||||
m_Settings = new QSettings(metaFileName, QSettings::IniFormat);
|
||||
|
||||
QLineEdit *modIDEdit = findChild<QLineEdit*>("modIDEdit");
|
||||
modIDEdit->setValidator(new QIntValidator(modIDEdit));
|
||||
modIDEdit->setText(QString("%1").arg(modInfo->getNexusID()));
|
||||
ui->modIDEdit->setValidator(new QIntValidator(modIDEdit));
|
||||
ui->modIDEdit->setText(QString("%1").arg(modInfo->getNexusID()));
|
||||
|
||||
ui->notesEdit->setText(modInfo->notes());
|
||||
|
||||
m_FileSystemModel = new QFileSystemModel(this);
|
||||
m_FileSystemModel->setReadOnly(false);
|
||||
m_FileSystemModel->setRootPath(m_RootPath);
|
||||
m_FileTree->setModel(m_FileSystemModel);
|
||||
m_FileTree->setRootIndex(m_FileSystemModel->index(m_RootPath));
|
||||
m_FileTree->setColumnWidth(0, 300);
|
||||
|
||||
connect(&m_ThumbnailMapper, SIGNAL(mapped(const QString&)), this, SIGNAL(thumbnailClickedSignal(const QString&)));
|
||||
connect(this, SIGNAL(thumbnailClickedSignal(const QString&)), this, SLOT(thumbnailClicked(const QString&)));
|
||||
|
||||
m_DeleteAction = new QAction(tr("&Delete"), m_FileTree);
|
||||
m_RenameAction = new QAction(tr("&Rename"), m_FileTree);
|
||||
m_HideAction = new QAction(tr("&Hide"), m_FileTree);
|
||||
m_UnhideAction = new QAction(tr("&Unhide"), m_FileTree);
|
||||
m_OpenAction = new QAction(tr("&Open"), m_FileTree);
|
||||
m_NewFolderAction = new QAction(tr("&New Folder"), m_FileTree);
|
||||
QObject::connect(m_DeleteAction, SIGNAL(triggered()), this, SLOT(deleteTriggered()));
|
||||
QObject::connect(m_RenameAction, SIGNAL(triggered()), this, SLOT(renameTriggered()));
|
||||
QObject::connect(m_OpenAction, SIGNAL(triggered()), this, SLOT(openTriggered()));
|
||||
QObject::connect(m_NewFolderAction, SIGNAL(triggered()), this, SLOT(createDirectoryTriggered()));
|
||||
QObject::connect(m_HideAction, SIGNAL(triggered()), this, SLOT(hideTriggered()));
|
||||
connect(m_UnhideAction, SIGNAL(triggered()), this, SLOT(unhideTriggered()));
|
||||
connect(m_ModInfo.data(), SIGNAL(modDetailsUpdated(bool)), this, SLOT(modDetailsUpdated(bool)));
|
||||
|
||||
// ui->descriptionView->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
|
||||
// QObject::connect(ui->descriptionView, SIGNAL(linkClicked(QUrl)), this, SLOT(linkClicked(QUrl)));
|
||||
connect(ui->descriptionView, SIGNAL(anchorClicked(QUrl)), this, SLOT(linkClicked(QUrl)));
|
||||
|
||||
if (directory->originExists(ToWString(modInfo->name()))) {
|
||||
@@ -126,32 +91,39 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
|
||||
}
|
||||
}
|
||||
|
||||
addCategories(CategoryFactory::instance(), modInfo->getCategories(), categoriesTree->invisibleRootItem(), 0);
|
||||
refreshPrimaryCategoriesBox();
|
||||
if (unmanaged) {
|
||||
ui->tabWidget->setTabEnabled(TAB_INIFILES, false);
|
||||
ui->tabWidget->setTabEnabled(TAB_CATEGORIES, false);
|
||||
ui->tabWidget->setTabEnabled(TAB_NEXUS, false);
|
||||
ui->tabWidget->setTabEnabled(TAB_FILETREE, false);
|
||||
ui->tabWidget->setTabEnabled(TAB_NOTES, false);
|
||||
} else {
|
||||
initFiletree(modInfo);
|
||||
initINITweaks();
|
||||
addCategories(CategoryFactory::instance(), modInfo->getCategories(), ui->categoriesTree->invisibleRootItem(), 0);
|
||||
refreshPrimaryCategoriesBox();
|
||||
}
|
||||
refreshLists();
|
||||
|
||||
int numTweaks = m_Settings->beginReadArray("INI Tweaks");
|
||||
for (int i = 0; i < numTweaks; ++i) {
|
||||
m_Settings->setArrayIndex(i);
|
||||
QList<QListWidgetItem*> items = iniTweaksList->findItems(m_Settings->value("name").toString(), Qt::MatchFixedString);
|
||||
if (items.size() != 0) {
|
||||
items.at(0)->setCheckState(Qt::Checked);
|
||||
}
|
||||
}
|
||||
m_Settings->endArray();
|
||||
ui->tabWidget->setTabEnabled(TAB_TEXTFILES, ui->textFileList->count() != 0);
|
||||
ui->tabWidget->setTabEnabled(TAB_IMAGES, ui->thumbnailArea->count() != 0);
|
||||
ui->tabWidget->setTabEnabled(TAB_ESPS, (ui->inactiveESPList->count() != 0) || (ui->activeESPList->count() != 0));
|
||||
ui->tabWidget->setTabEnabled(TAB_CONFLICTS, m_Origin != NULL);
|
||||
|
||||
QTabWidget *tabWidget = findChild<QTabWidget*>("tabWidget");
|
||||
tabWidget->setTabEnabled(TAB_TEXTFILES, textFileList->count() != 0);
|
||||
tabWidget->setTabEnabled(TAB_IMAGES, thumbnailArea->count() != 0);
|
||||
tabWidget->setTabEnabled(TAB_ESPS, (inactiveESPList->count() != 0) || (activeESPList->count() != 0));
|
||||
tabWidget->setTabEnabled(TAB_CONFLICTS, m_Origin != NULL);
|
||||
|
||||
if (tabWidget->currentIndex() == TAB_NEXUS) {
|
||||
if (ui->tabWidget->currentIndex() == TAB_NEXUS) {
|
||||
activateNexusTab();
|
||||
}
|
||||
|
||||
ui->endorseBtn->setEnabled((m_ModInfo->endorsedState() == ModInfo::ENDORSED_FALSE) ||
|
||||
(m_ModInfo->endorsedState() == ModInfo::ENDORSED_NEVER));
|
||||
|
||||
// activate first enabled tab
|
||||
for (int i = 0; i < ui->tabWidget->count(); ++i) {
|
||||
if (ui->tabWidget->isTabEnabled(i)) {
|
||||
ui->tabWidget->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -165,6 +137,46 @@ ModInfoDialog::~ModInfoDialog()
|
||||
}
|
||||
|
||||
|
||||
void ModInfoDialog::initINITweaks()
|
||||
{
|
||||
int numTweaks = m_Settings->beginReadArray("INI Tweaks");
|
||||
for (int i = 0; i < numTweaks; ++i) {
|
||||
m_Settings->setArrayIndex(i);
|
||||
QList<QListWidgetItem*> items = ui->iniTweaksList->findItems(m_Settings->value("name").toString(), Qt::MatchFixedString);
|
||||
if (items.size() != 0) {
|
||||
items.at(0)->setCheckState(Qt::Checked);
|
||||
}
|
||||
}
|
||||
m_Settings->endArray();
|
||||
}
|
||||
|
||||
void ModInfoDialog::initFiletree(ModInfo::Ptr modInfo)
|
||||
{
|
||||
m_RootPath = modInfo->absolutePath();
|
||||
ui->fileTree = findChild<QTreeView*>("fileTree");
|
||||
|
||||
m_FileSystemModel = new QFileSystemModel(this);
|
||||
m_FileSystemModel->setReadOnly(false);
|
||||
m_FileSystemModel->setRootPath(m_RootPath);
|
||||
ui->fileTree->setModel(m_FileSystemModel);
|
||||
ui->fileTree->setRootIndex(m_FileSystemModel->index(m_RootPath));
|
||||
ui->fileTree->setColumnWidth(0, 300);
|
||||
|
||||
m_DeleteAction = new QAction(tr("&Delete"), ui->fileTree);
|
||||
m_RenameAction = new QAction(tr("&Rename"), ui->fileTree);
|
||||
m_HideAction = new QAction(tr("&Hide"), ui->fileTree);
|
||||
m_UnhideAction = new QAction(tr("&Unhide"), ui->fileTree);
|
||||
m_OpenAction = new QAction(tr("&Open"), ui->fileTree);
|
||||
m_NewFolderAction = new QAction(tr("&New Folder"), ui->fileTree);
|
||||
QObject::connect(m_DeleteAction, SIGNAL(triggered()), this, SLOT(deleteTriggered()));
|
||||
QObject::connect(m_RenameAction, SIGNAL(triggered()), this, SLOT(renameTriggered()));
|
||||
QObject::connect(m_OpenAction, SIGNAL(triggered()), this, SLOT(openTriggered()));
|
||||
QObject::connect(m_NewFolderAction, SIGNAL(triggered()), this, SLOT(createDirectoryTriggered()));
|
||||
QObject::connect(m_HideAction, SIGNAL(triggered()), this, SLOT(hideTriggered()));
|
||||
connect(m_UnhideAction, SIGNAL(triggered()), this, SLOT(unhideTriggered()));
|
||||
}
|
||||
|
||||
|
||||
int ModInfoDialog::tabIndex(const QString &tabId)
|
||||
{
|
||||
for (int i = 0; i < ui->tabWidget->count(); ++i) {
|
||||
@@ -271,51 +283,52 @@ void ModInfoDialog::refreshLists()
|
||||
}
|
||||
}
|
||||
|
||||
if (m_RootPath.length() > 0) {
|
||||
QDirIterator dirIterator(m_RootPath, QDir::Files, QDirIterator::Subdirectories);
|
||||
while (dirIterator.hasNext()) {
|
||||
QString fileName = dirIterator.next();
|
||||
|
||||
QDirIterator dirIterator(m_RootPath, QDir::Files, QDirIterator::Subdirectories);
|
||||
while (dirIterator.hasNext()) {
|
||||
QString fileName = dirIterator.next();
|
||||
|
||||
if (fileName.endsWith(".txt", Qt::CaseInsensitive)) {
|
||||
ui->textFileList->addItem(fileName.mid(m_RootPath.length() + 1));
|
||||
} else if ((fileName.endsWith(".ini", Qt::CaseInsensitive) || fileName.endsWith(".cfg", Qt::CaseInsensitive)) &&
|
||||
!fileName.endsWith("meta.ini")) {
|
||||
QString namePart = fileName.mid(m_RootPath.length() + 1);
|
||||
if (namePart.startsWith("INI Tweaks", Qt::CaseInsensitive)) {
|
||||
QListWidgetItem *newItem = new QListWidgetItem(namePart.mid(11), ui->iniTweaksList);
|
||||
newItem->setData(Qt::UserRole, namePart);
|
||||
newItem->setFlags(newItem->flags() | Qt::ItemIsUserCheckable);
|
||||
newItem->setCheckState(Qt::Unchecked);
|
||||
ui->iniTweaksList->addItem(newItem);
|
||||
} else {
|
||||
ui->iniFileList->addItem(namePart);
|
||||
}
|
||||
} else if (fileName.endsWith(".esp", Qt::CaseInsensitive) ||
|
||||
fileName.endsWith(".esm", Qt::CaseInsensitive)) {
|
||||
QString relativePath = fileName.mid(m_RootPath.length() + 1);
|
||||
if (relativePath.contains('/')) {
|
||||
QFileInfo fileInfo(fileName);
|
||||
QListWidgetItem *newItem = new QListWidgetItem(fileInfo.fileName());
|
||||
newItem->setData(Qt::UserRole, relativePath);
|
||||
ui->inactiveESPList->addItem(newItem);
|
||||
} else {
|
||||
ui->activeESPList->addItem(relativePath);
|
||||
}
|
||||
} else if ((fileName.endsWith(".png", Qt::CaseInsensitive)) ||
|
||||
(fileName.endsWith(".jpg", Qt::CaseInsensitive))) {
|
||||
QImage image = QImage(fileName);
|
||||
if (!image.isNull()) {
|
||||
if (static_cast<float>(image.width()) / static_cast<float>(image.height()) > 1.34) {
|
||||
image = image.scaledToWidth(128);
|
||||
if (fileName.endsWith(".txt", Qt::CaseInsensitive)) {
|
||||
ui->textFileList->addItem(fileName.mid(m_RootPath.length() + 1));
|
||||
} else if ((fileName.endsWith(".ini", Qt::CaseInsensitive) || fileName.endsWith(".cfg", Qt::CaseInsensitive)) &&
|
||||
!fileName.endsWith("meta.ini")) {
|
||||
QString namePart = fileName.mid(m_RootPath.length() + 1);
|
||||
if (namePart.startsWith("INI Tweaks", Qt::CaseInsensitive)) {
|
||||
QListWidgetItem *newItem = new QListWidgetItem(namePart.mid(11), ui->iniTweaksList);
|
||||
newItem->setData(Qt::UserRole, namePart);
|
||||
newItem->setFlags(newItem->flags() | Qt::ItemIsUserCheckable);
|
||||
newItem->setCheckState(Qt::Unchecked);
|
||||
ui->iniTweaksList->addItem(newItem);
|
||||
} else {
|
||||
image = image.scaledToHeight(96);
|
||||
ui->iniFileList->addItem(namePart);
|
||||
}
|
||||
} else if (fileName.endsWith(".esp", Qt::CaseInsensitive) ||
|
||||
fileName.endsWith(".esm", Qt::CaseInsensitive)) {
|
||||
QString relativePath = fileName.mid(m_RootPath.length() + 1);
|
||||
if (relativePath.contains('/')) {
|
||||
QFileInfo fileInfo(fileName);
|
||||
QListWidgetItem *newItem = new QListWidgetItem(fileInfo.fileName());
|
||||
newItem->setData(Qt::UserRole, relativePath);
|
||||
ui->inactiveESPList->addItem(newItem);
|
||||
} else {
|
||||
ui->activeESPList->addItem(relativePath);
|
||||
}
|
||||
} else if ((fileName.endsWith(".png", Qt::CaseInsensitive)) ||
|
||||
(fileName.endsWith(".jpg", Qt::CaseInsensitive))) {
|
||||
QImage image = QImage(fileName);
|
||||
if (!image.isNull()) {
|
||||
if (static_cast<float>(image.width()) / static_cast<float>(image.height()) > 1.34) {
|
||||
image = image.scaledToWidth(128);
|
||||
} else {
|
||||
image = image.scaledToHeight(96);
|
||||
}
|
||||
|
||||
QPushButton *thumbnailButton = new QPushButton(QPixmap::fromImage(image), "");
|
||||
thumbnailButton->setIconSize(QSize(image.width(), image.height()));
|
||||
connect(thumbnailButton, SIGNAL(clicked()), &m_ThumbnailMapper, SLOT(map()));
|
||||
m_ThumbnailMapper.setMapping(thumbnailButton, fileName);
|
||||
ui->thumbnailArea->addWidget(thumbnailButton);
|
||||
QPushButton *thumbnailButton = new QPushButton(QPixmap::fromImage(image), "");
|
||||
thumbnailButton->setIconSize(QSize(image.width(), image.height()));
|
||||
connect(thumbnailButton, SIGNAL(clicked()), &m_ThumbnailMapper, SLOT(map()));
|
||||
m_ThumbnailMapper.setMapping(thumbnailButton, fileName);
|
||||
ui->thumbnailArea->addWidget(thumbnailButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,7 +473,8 @@ void ModInfoDialog::openIniFile(const QString &fileName)
|
||||
QFile iniFile(fileName);
|
||||
iniFile.open(QIODevice::ReadOnly);
|
||||
QByteArray buffer = iniFile.readAll();
|
||||
QTextCodec *codec = QTextCodec::codecForUtfText(buffer, m_UTF8Codec);
|
||||
|
||||
QTextCodec *codec = QTextCodec::codecForUtfText(buffer, QTextCodec::codecForName("utf-8"));
|
||||
QTextEdit *iniFileView = findChild<QTextEdit*>("iniFileView");
|
||||
iniFileView->setText(codec->toUnicode(buffer));
|
||||
iniFileView->setProperty("currentFile", fileName);
|
||||
@@ -929,7 +943,7 @@ void ModInfoDialog::renameTriggered()
|
||||
return;
|
||||
}
|
||||
|
||||
m_FileTree->edit(index);
|
||||
ui->fileTree->edit(index);
|
||||
}
|
||||
|
||||
|
||||
@@ -999,18 +1013,18 @@ void ModInfoDialog::createDirectoryTriggered()
|
||||
return;
|
||||
}
|
||||
|
||||
m_FileTree->setCurrentIndex(newIndex);
|
||||
m_FileTree->edit(newIndex);
|
||||
ui->fileTree->setCurrentIndex(newIndex);
|
||||
ui->fileTree->edit(newIndex);
|
||||
}
|
||||
|
||||
|
||||
void ModInfoDialog::on_fileTree_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QItemSelectionModel *selectionModel = m_FileTree->selectionModel();
|
||||
QItemSelectionModel *selectionModel = ui->fileTree->selectionModel();
|
||||
m_FileSelection = selectionModel->selectedRows(0);
|
||||
|
||||
// m_FileSelection = m_FileTree->indexAt(pos);
|
||||
QMenu menu(m_FileTree);
|
||||
// m_FileSelection = ui->fileTree->indexAt(pos);
|
||||
QMenu menu(ui->fileTree);
|
||||
|
||||
menu.addAction(m_NewFolderAction);
|
||||
|
||||
@@ -1038,7 +1052,7 @@ void ModInfoDialog::on_fileTree_customContextMenuRequested(const QPoint &pos)
|
||||
m_FileSelection.clear();
|
||||
m_FileSelection.append(m_FileSystemModel->index(m_FileSystemModel->rootPath(), 0));
|
||||
}
|
||||
menu.exec(m_FileTree->mapToGlobal(pos));
|
||||
menu.exec(ui->fileTree->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
|
||||
@@ -1164,18 +1178,17 @@ void ModInfoDialog::on_overwriteTree_customContextMenuRequested(const QPoint &po
|
||||
{
|
||||
m_ConflictsContextItem = ui->overwriteTree->itemAt(pos.x(), pos.y());
|
||||
|
||||
QMenu menu;
|
||||
if (m_ConflictsContextItem != NULL) {
|
||||
// offer to hide/unhide file, but not for files from archives
|
||||
// if (!m_ConflictsContextItem->data(0, Qt::UserRole + 1).toBool()) {
|
||||
if (!m_ConflictsContextItem->data(0, Qt::UserRole + 2).toBool()) {
|
||||
if (!m_ConflictsContextItem->data(1, Qt::UserRole + 2).toBool()) {
|
||||
QMenu menu;
|
||||
if (m_ConflictsContextItem->text(0).endsWith(ModInfo::s_HiddenExt)) {
|
||||
menu.addAction(tr("Un-Hide"), this, SLOT(unhideConflictFile()));
|
||||
} else {
|
||||
menu.addAction(tr("Hide"), this, SLOT(hideConflictFile()));
|
||||
}
|
||||
menu.exec(ui->overwriteTree->mapToGlobal(pos));
|
||||
}
|
||||
menu.exec(ui->overwriteTree->mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -65,6 +65,7 @@ public:
|
||||
TAB_CONFLICTS,
|
||||
TAB_CATEGORIES,
|
||||
TAB_NEXUS,
|
||||
TAB_NOTES,
|
||||
TAB_FILETREE
|
||||
};
|
||||
|
||||
@@ -76,7 +77,7 @@ public:
|
||||
* @param modInfo info structure about the mod to display
|
||||
* @param parent parend widget
|
||||
**/
|
||||
explicit ModInfoDialog(ModInfo::Ptr modInfo, const MOShared::DirectoryEntry *directory, QWidget *parent = 0);
|
||||
explicit ModInfoDialog(ModInfo::Ptr modInfo, const MOShared::DirectoryEntry *directory, bool unmanaged, QWidget *parent = 0);
|
||||
~ModInfoDialog();
|
||||
|
||||
/**
|
||||
@@ -121,6 +122,9 @@ public slots:
|
||||
|
||||
private:
|
||||
|
||||
void initFiletree(ModInfo::Ptr modInfo);
|
||||
void initINITweaks();
|
||||
|
||||
void refreshLists();
|
||||
|
||||
void addCategories(const CategoryFactory &factory, const std::set<int> &enabledCategories, QTreeWidgetItem *root, int rootLevel);
|
||||
@@ -225,7 +229,6 @@ private:
|
||||
|
||||
const MOShared::DirectoryEntry *m_Directory;
|
||||
MOShared::FilesOrigin *m_Origin;
|
||||
QTextCodec *m_UTF8Codec;
|
||||
|
||||
std::map<int, int> m_RealTabPos;
|
||||
|
||||
|
||||
+21
-16
@@ -166,25 +166,29 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
} else if (column == COL_CATEGORY) {
|
||||
int category = modInfo->getPrimaryCategory();
|
||||
if (category != -1) {
|
||||
CategoryFactory &categoryFactory = CategoryFactory::instance();
|
||||
if (categoryFactory.categoryExists(category)) {
|
||||
try {
|
||||
int categoryIdx = categoryFactory.getCategoryIndex(category);
|
||||
return categoryFactory.getCategoryName(categoryIdx);
|
||||
} catch (const std::exception &e) {
|
||||
qCritical("failed to retrieve category name: %s", e.what());
|
||||
if (modInfo->hasFlag(ModInfo::FLAG_FOREIGN)) {
|
||||
return tr("Non-MO");
|
||||
} else {
|
||||
int category = modInfo->getPrimaryCategory();
|
||||
if (category != -1) {
|
||||
CategoryFactory &categoryFactory = CategoryFactory::instance();
|
||||
if (categoryFactory.categoryExists(category)) {
|
||||
try {
|
||||
int categoryIdx = categoryFactory.getCategoryIndex(category);
|
||||
return categoryFactory.getCategoryName(categoryIdx);
|
||||
} catch (const std::exception &e) {
|
||||
qCritical("failed to retrieve category name: %s", e.what());
|
||||
return QString();
|
||||
}
|
||||
} else {
|
||||
qWarning("category %d doesn't exist (may have been removed)", category);
|
||||
modInfo->setCategory(category, false);
|
||||
return QString();
|
||||
}
|
||||
} else {
|
||||
qWarning("category %d doesn't exist (may have been removed)", category);
|
||||
modInfo->setCategory(category, false);
|
||||
return QString();
|
||||
//return tr("None");
|
||||
return QVariant();
|
||||
}
|
||||
} else {
|
||||
//return tr("None");
|
||||
return QVariant();
|
||||
}
|
||||
} else if (column == COL_INSTALLTIME) {
|
||||
// display installation time for mods that can be updated
|
||||
@@ -253,6 +257,8 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
|
||||
if (modInfo->getHighlight() & ModInfo::HIGHLIGHT_INVALID) {
|
||||
result.setItalic(true);
|
||||
}
|
||||
} else if ((column == COL_CATEGORY) && (modInfo->hasFlag(ModInfo::FLAG_FOREIGN))) {
|
||||
result.setItalic(true);
|
||||
} else if (column == COL_VERSION) {
|
||||
if (modInfo->updateAvailable() || modInfo->downgradeAvailable()) {
|
||||
result.setWeight(QFont::Bold);
|
||||
@@ -650,7 +656,6 @@ bool ModList::setPriority(const QString &name, int newPriority)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ModList::onModStateChanged(const std::function<void (const QString &, IModList::ModStates)> &func)
|
||||
{
|
||||
auto conn = m_ModStateChanged.connect(func);
|
||||
|
||||
@@ -248,6 +248,12 @@ bool ModListSortProxy::filterMatchesModAnd(ModInfo::Ptr info, bool enabled) cons
|
||||
ModInfo::EEndorsedState state = info->endorsedState();
|
||||
if (state != ModInfo::ENDORSED_FALSE) return false;
|
||||
} break;
|
||||
case CategoryFactory::CATEGORY_SPECIAL_MANAGED: {
|
||||
if (info->hasFlag(ModInfo::FLAG_FOREIGN)) return false;
|
||||
} break;
|
||||
case CategoryFactory::CATEGORY_SPECIAL_UNMANAGED: {
|
||||
if (!info->hasFlag(ModInfo::FLAG_FOREIGN)) return false;
|
||||
} break;
|
||||
default: {
|
||||
if (!info->categorySet(*iter)) return false;
|
||||
} break;
|
||||
@@ -279,6 +285,12 @@ bool ModListSortProxy::filterMatchesModOr(ModInfo::Ptr info, bool enabled) const
|
||||
ModInfo::EEndorsedState state = info->endorsedState();
|
||||
if ((state == ModInfo::ENDORSED_FALSE) && (state != ModInfo::ENDORSED_NEVER)) return true;
|
||||
} break;
|
||||
case CategoryFactory::CATEGORY_SPECIAL_MANAGED: {
|
||||
if (!info->hasFlag(ModInfo::FLAG_FOREIGN)) return true;
|
||||
} break;
|
||||
case CategoryFactory::CATEGORY_SPECIAL_UNMANAGED: {
|
||||
if (info->hasFlag(ModInfo::FLAG_FOREIGN)) return true;
|
||||
} break;
|
||||
default: {
|
||||
if (info->categorySet(*iter)) return true;
|
||||
} break;
|
||||
|
||||
@@ -122,7 +122,7 @@ void NXMAccessManager::login(const QString &username, const QString &password)
|
||||
|
||||
void NXMAccessManager::pageLogin()
|
||||
{
|
||||
QString requestString = QString("http://gatekeeper.nexusmods.com/Sessions/?Login&uri=%1")
|
||||
QString requestString = (ToQString(GameInfo::instance().getNexusPage(false)) + "/sessions/?Login&uri=%1")
|
||||
.arg(QString(QUrl::toPercentEncoding(ToQString(GameInfo::instance().getNexusPage()))));
|
||||
|
||||
QNetworkRequest request(requestString);
|
||||
|
||||
+2
-1
@@ -321,7 +321,8 @@ OTHER_FILES += \
|
||||
dark.qss \
|
||||
stylesheets/dark.qss \
|
||||
tutorials/tutorial_window_installer.js \
|
||||
tutorials/tutorials_installdialog.qml
|
||||
tutorials/tutorials_installdialog.qml \
|
||||
tutorials/tutorial_firststeps_settings.js
|
||||
|
||||
|
||||
# leak detection with vld
|
||||
|
||||
+11
-2
@@ -216,12 +216,12 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD
|
||||
}
|
||||
|
||||
|
||||
void PluginList::enableESP(const QString &name)
|
||||
void PluginList::enableESP(const QString &name, bool enable)
|
||||
{
|
||||
std::map<QString, int>::iterator iter = m_ESPsByName.find(name.toLower());
|
||||
|
||||
if (iter != m_ESPsByName.end()) {
|
||||
m_ESPs[iter->second].m_Enabled = true;
|
||||
m_ESPs[iter->second].m_Enabled = enable;
|
||||
startSaveTime();
|
||||
} else {
|
||||
reportError(tr("esp not found: %1").arg(name));
|
||||
@@ -677,6 +677,14 @@ bool PluginList::onRefreshed(const std::function<void ()> &callback)
|
||||
return conn.connected();
|
||||
}
|
||||
|
||||
|
||||
bool PluginList::onPluginMoved(const std::function<void (const QString &, int, int)> &func)
|
||||
{
|
||||
auto conn = m_PluginMoved.connect(func);
|
||||
return conn.connected();
|
||||
}
|
||||
|
||||
|
||||
void PluginList::updateIndices()
|
||||
{
|
||||
m_ESPsByName.clear();
|
||||
@@ -947,6 +955,7 @@ void PluginList::setPluginPriority(int row, int &newPriority)
|
||||
|
||||
m_ESPs.at(row).m_Priority = newPriorityTemp;
|
||||
emit dataChanged(index(row, 0), index(row, columnCount()));
|
||||
m_PluginMoved(m_ESPs[row].m_Name, oldPriority, newPriorityTemp);
|
||||
} catch (const std::out_of_range&) {
|
||||
reportError(tr("failed to restore load order for %1").arg(m_ESPs[row].m_Name));
|
||||
}
|
||||
|
||||
+6
-1
@@ -86,6 +86,7 @@ public:
|
||||
};
|
||||
|
||||
typedef boost::signals2::signal<void ()> SignalRefreshed;
|
||||
typedef boost::signals2::signal<void (const QString &, int, int)> SignalPluginMoved;
|
||||
|
||||
public:
|
||||
|
||||
@@ -118,8 +119,9 @@ public:
|
||||
* @brief enable a plugin based on its name
|
||||
*
|
||||
* @param name name of the plugin to enable
|
||||
* @param enable set to true to enable the esp, false to disable it
|
||||
**/
|
||||
void enableESP(const QString &name);
|
||||
void enableESP(const QString &name, bool enable = true);
|
||||
|
||||
/**
|
||||
* @brief test if a plugin is enabled
|
||||
@@ -218,6 +220,7 @@ public:
|
||||
virtual bool isMaster(const QString &name) const;
|
||||
virtual QString origin(const QString &name) const;
|
||||
virtual bool onRefreshed(const std::function<void()> &callback);
|
||||
virtual bool onPluginMoved(const std::function<void (const QString &, int, int)> &func);
|
||||
|
||||
public: // implementation of the QAbstractTableModel interface
|
||||
|
||||
@@ -332,6 +335,8 @@ private:
|
||||
|
||||
QTemporaryFile m_TempFile;
|
||||
|
||||
SignalPluginMoved m_PluginMoved;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -419,7 +419,6 @@ void Profile::setModEnabled(unsigned int index, bool enabled)
|
||||
// overwrite is always enabled
|
||||
return;
|
||||
}
|
||||
|
||||
if (enabled != m_ModStatus[index].m_Enabled) {
|
||||
m_ModStatus[index].m_Enabled = enabled;
|
||||
emit modStatusChanged(index);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user