mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b23a4885e0 | ||
|
|
823dfd410b | ||
|
|
ba09054e6b | ||
|
|
694e3ed279 | ||
|
|
cffd9eb4e2 | ||
|
|
640b14ef25 | ||
|
|
47293827bb | ||
|
|
0a3169b808 | ||
|
|
f4528c7aaa | ||
|
|
4f0a6e8b88 | ||
|
|
c57b172204 | ||
|
|
dfca8be71b | ||
|
|
08037bf876 | ||
|
|
500ab7f706 | ||
|
|
08309b71ba |
@@ -65,11 +65,6 @@ ActivateModsDialog::~ActivateModsDialog()
|
||||
}
|
||||
|
||||
|
||||
void ActivateModsDialog::on_buttonBox_accepted()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::set<QString> ActivateModsDialog::getModsToActivate()
|
||||
{
|
||||
std::set<QString> result;
|
||||
|
||||
@@ -62,7 +62,6 @@ public:
|
||||
std::set<QString> getESPsToActivate();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
private:
|
||||
Ui::ActivateModsDialog *ui;
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
|
||||
|
||||
This file is part of Mod Organizer.
|
||||
|
||||
Mod Organizer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Mod Organizer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "archivetree.h"
|
||||
#include <QDragMoveEvent>
|
||||
|
||||
ArchiveTree::ArchiveTree(QWidget *parent) :
|
||||
QTreeWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool ArchiveTree::testMovePossible(QTreeWidgetItem *source, QTreeWidgetItem *target)
|
||||
{
|
||||
if ((target == NULL) ||
|
||||
(source == NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((source == target) ||
|
||||
(source->parent() == target)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArchiveTree::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
QTreeWidgetItem *source = this->currentItem();
|
||||
if ((source == NULL) || (source->parent() == NULL)) {
|
||||
// can't change top level
|
||||
event->ignore();
|
||||
return;
|
||||
} else {
|
||||
QTreeWidget::dragEnterEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ArchiveTree::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
if (!testMovePossible(this->currentItem(), itemAt(event->pos()))) {
|
||||
event->ignore();
|
||||
} else {
|
||||
QTreeWidget::dragMoveEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArchiveTree::dropEvent(QDropEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
|
||||
QTreeWidgetItem *target = itemAt(event->pos());
|
||||
|
||||
QList<QTreeWidgetItem*> sourceItems = this->selectedItems();
|
||||
for (QList<QTreeWidgetItem*>::iterator iter = sourceItems.begin();
|
||||
iter != sourceItems.end(); ++iter) {
|
||||
QTreeWidgetItem *source = *iter;
|
||||
if ((source->parent() != NULL) &&
|
||||
testMovePossible(source, target)) {
|
||||
source->parent()->removeChild(source);
|
||||
if (target->data(0, Qt::UserRole).toInt() != 0) {
|
||||
// target is a file
|
||||
if (target->parent() == NULL) {
|
||||
// this should really not happen, how should a
|
||||
// file get to the top level?
|
||||
return;
|
||||
}
|
||||
int index = target->parent()->indexOfChild(target);
|
||||
target->parent()->insertChild(index, source);
|
||||
emit changed();
|
||||
} else {
|
||||
// target is a directory
|
||||
target->insertChild(target->childCount(), source);
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
|
||||
|
||||
This file is part of Mod Organizer.
|
||||
|
||||
Mod Organizer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Mod Organizer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVETREE_H
|
||||
#define ARCHIVETREE_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
|
||||
/**
|
||||
* @brief QT tree widget used to display the content of an archive in the manual installation dialog
|
||||
**/
|
||||
class ArchiveTree : public QTreeWidget
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ArchiveTree(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
void changed();
|
||||
|
||||
public slots:
|
||||
|
||||
protected:
|
||||
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event);
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event);
|
||||
virtual void dropEvent(QDropEvent *event);
|
||||
|
||||
private:
|
||||
|
||||
bool testMovePossible(QTreeWidgetItem *source, QTreeWidgetItem *target);
|
||||
|
||||
};
|
||||
|
||||
#endif // ARCHIVETREE_H
|
||||
@@ -43,6 +43,7 @@ QString CategoryFactory::categoriesFilePath()
|
||||
|
||||
CategoryFactory::CategoryFactory()
|
||||
{
|
||||
atexit(&cleanup);
|
||||
reset();
|
||||
|
||||
QFile categoryFile(categoriesFilePath());
|
||||
@@ -124,6 +125,12 @@ void CategoryFactory::setParents()
|
||||
}
|
||||
}
|
||||
|
||||
void CategoryFactory::cleanup()
|
||||
{
|
||||
delete s_Instance;
|
||||
s_Instance = NULL;
|
||||
}
|
||||
|
||||
|
||||
void CategoryFactory::saveCategories()
|
||||
{
|
||||
|
||||
@@ -180,6 +180,8 @@ private:
|
||||
|
||||
void setParents();
|
||||
|
||||
static void cleanup();
|
||||
|
||||
private:
|
||||
|
||||
static CategoryFactory *s_Instance;
|
||||
@@ -188,6 +190,8 @@ private:
|
||||
std::map<int, unsigned int> m_IDMap;
|
||||
std::map<int, unsigned int> m_NexusMap;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "nxmurl.h"
|
||||
#include <gameinfo.h>
|
||||
#include <nxmurl.h>
|
||||
#include <taskprogressmanager.h>
|
||||
#include "utility.h"
|
||||
#include "json.h"
|
||||
#include "selectiondialog.h"
|
||||
@@ -63,6 +64,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Ne
|
||||
info->m_CurrentUrl = 0;
|
||||
info->m_Tries = AUTOMATIC_RETRIES;
|
||||
info->m_State = STATE_STARTED;
|
||||
info->m_TaskProgressId = TaskProgressManager::instance().getId();
|
||||
|
||||
return info;
|
||||
}
|
||||
@@ -105,6 +107,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con
|
||||
info->m_CurrentUrl = 0;
|
||||
info->m_Urls = metaFile.value("url", "").toString().split(";");
|
||||
info->m_Tries = 0;
|
||||
info->m_TaskProgressId = TaskProgressManager::instance().getId();
|
||||
info->m_NexusInfo.m_Name = metaFile.value("name", 0).toString();
|
||||
info->m_NexusInfo.m_ModName = metaFile.value("modName", "").toString();
|
||||
info->m_NexusInfo.m_Version = metaFile.value("version", 0).toString();
|
||||
@@ -159,6 +162,7 @@ DownloadManager::~DownloadManager()
|
||||
for (QVector<DownloadInfo*>::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
m_ActiveDownloads.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -805,6 +809,7 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
}
|
||||
int oldProgress = info->m_Progress;
|
||||
info->m_Progress = ((info->m_ResumePos + bytesReceived) * 100) / (info->m_ResumePos + bytesTotal);
|
||||
TaskProgressManager::instance().updateProgress(info->m_TaskProgressId, bytesReceived, bytesTotal);
|
||||
if (oldProgress != info->m_Progress) {
|
||||
emit update(index);
|
||||
}
|
||||
|
||||
@@ -98,6 +98,8 @@ private:
|
||||
int m_Tries;
|
||||
bool m_ReQueried;
|
||||
|
||||
quint32 m_TaskProgressId;
|
||||
|
||||
NexusInfo m_NexusInfo;
|
||||
|
||||
static DownloadInfo *createNew(const NexusInfo &nexusInfo, int modID, int fileID, const QStringList &URLs);
|
||||
|
||||
@@ -172,16 +172,6 @@ void ExecutablesList::addExecutable(const QString &title, const QString &executa
|
||||
}
|
||||
}
|
||||
|
||||
/*void ExecutablesList::remove(const QString &executableName)
|
||||
{
|
||||
for (std::vector<Executable>::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) {
|
||||
if (iter->m_Custom && (iter->m_BinaryInfo.absoluteFilePath() == executableName)) {
|
||||
m_Executables.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
void ExecutablesList::remove(const QString &title)
|
||||
{
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
|
||||
|
||||
This file is part of Mod Organizer.
|
||||
|
||||
Mod Organizer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Mod Organizer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "finddialog.h"
|
||||
#include "ui_finddialog.h"
|
||||
|
||||
FindDialog::FindDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::FindDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
FindDialog::~FindDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FindDialog::on_nextBtn_clicked()
|
||||
{
|
||||
emit findNext();
|
||||
}
|
||||
|
||||
void FindDialog::on_patternEdit_textChanged(const QString &pattern)
|
||||
{
|
||||
emit patternChanged(pattern);
|
||||
}
|
||||
|
||||
void FindDialog::on_closeBtn_clicked()
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
|
||||
|
||||
This file is part of Mod Organizer.
|
||||
|
||||
Mod Organizer is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Mod Organizer is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FINDDIALOG_H
|
||||
#define FINDDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class FindDialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find dialog used in the TextView dialog
|
||||
**/
|
||||
class FindDialog : public QDialog
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
*
|
||||
* @param parent parent widget
|
||||
**/
|
||||
explicit FindDialog(QWidget *parent = 0);
|
||||
|
||||
~FindDialog();
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
* @brief emitted when the user wants to jump to the next location matching the pattern
|
||||
**/
|
||||
void findNext();
|
||||
|
||||
/**
|
||||
* @brief emitted when the user changes the pattern to search for
|
||||
*
|
||||
* @param pattern the new search pattern
|
||||
**/
|
||||
void patternChanged(const QString &pattern);
|
||||
|
||||
private slots:
|
||||
void on_nextBtn_clicked();
|
||||
|
||||
void on_patternEdit_textChanged(const QString &arg1);
|
||||
|
||||
void on_closeBtn_clicked();
|
||||
|
||||
private:
|
||||
Ui::FindDialog *ui;
|
||||
};
|
||||
|
||||
#endif // FINDDIALOG_H
|
||||
@@ -46,6 +46,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QDateTime>
|
||||
#include <QDirIterator>
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
|
||||
using namespace MOBase;
|
||||
@@ -678,8 +679,7 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
|
||||
this->m_CurrentArchive->close();
|
||||
});
|
||||
|
||||
DirectoryTree *filesTree = archiveOpen ? createFilesTree() : NULL;
|
||||
|
||||
QScopedPointer<DirectoryTree> filesTree(archiveOpen ? createFilesTree() : NULL);
|
||||
IPluginInstaller::EInstallResult installResult = IPluginInstaller::RESULT_NOTATTEMPTED;
|
||||
|
||||
std::sort(m_Installers.begin(), m_Installers.end(), [] (IPluginInstaller *LHS, IPluginInstaller *RHS) {
|
||||
@@ -704,7 +704,7 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
|
||||
(filesTree != NULL) && (installer->isArchiveSupported(*filesTree))) {
|
||||
installResult = installerSimple->install(modName, *filesTree, version, modID);
|
||||
if (installResult == IPluginInstaller::RESULT_SUCCESS) {
|
||||
mapToArchive(filesTree);
|
||||
mapToArchive(filesTree.data());
|
||||
// the simple installer only prepares the installation, the rest works the same for all installers
|
||||
if (!doInstall(modName, modID, version, newestVersion, categoryID)) {
|
||||
installResult = IPluginInstaller::RESULT_FAILED;
|
||||
|
||||
+53
-44
@@ -18,6 +18,11 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LEAK_CHECK_WITH_VLD
|
||||
#include <wchar.h>
|
||||
#include <vld.h>
|
||||
#endif // LEAK_CHECK_WITH_VLD
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
@@ -343,7 +348,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
if (!GameInfo::init(moPath, ToWString(gamePath))) {
|
||||
if (!GameInfo::init(moPath, ToWString(QDir::toNativeSeparators(gamePath)))) {
|
||||
if (!gamePath.isEmpty()) {
|
||||
reportError(QObject::tr("No game identified in \"%1\". The directory is required to contain "
|
||||
"the game binary and its launcher.").arg(gamePath));
|
||||
@@ -430,61 +435,65 @@ int main(int argc, char *argv[])
|
||||
|
||||
application.setStyleFile(settings.value("Settings/style", "").toString());
|
||||
|
||||
// set up main window and its data structures
|
||||
MainWindow mainWindow(argv[0], settings);
|
||||
QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString)));
|
||||
QObject::connect(&instance, SIGNAL(messageSent(QString)), &mainWindow, SLOT(externalMessage(QString)));
|
||||
int res = 1;
|
||||
{ // scope to control lifetime of mainwindow
|
||||
// set up main window and its data structures
|
||||
MainWindow mainWindow(argv[0], settings);
|
||||
QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString)));
|
||||
QObject::connect(&instance, SIGNAL(messageSent(QString)), &mainWindow, SLOT(externalMessage(QString)));
|
||||
|
||||
mainWindow.setExecutablesList(executablesList);
|
||||
mainWindow.readSettings();
|
||||
mainWindow.setExecutablesList(executablesList);
|
||||
mainWindow.readSettings();
|
||||
|
||||
QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray());
|
||||
QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray());
|
||||
|
||||
{ // see if there is a profile on the command line
|
||||
int profileIndex = arguments.indexOf("-p", 1);
|
||||
if ((profileIndex != -1) && (profileIndex < arguments.size() - 1)) {
|
||||
qDebug("profile overwritten on command line");
|
||||
selectedProfileName = arguments.at(profileIndex + 1);
|
||||
{ // see if there is a profile on the command line
|
||||
int profileIndex = arguments.indexOf("-p", 1);
|
||||
if ((profileIndex != -1) && (profileIndex < arguments.size() - 1)) {
|
||||
qDebug("profile overwritten on command line");
|
||||
selectedProfileName = arguments.at(profileIndex + 1);
|
||||
}
|
||||
arguments.removeAt(profileIndex);
|
||||
arguments.removeAt(profileIndex);
|
||||
}
|
||||
arguments.removeAt(profileIndex);
|
||||
arguments.removeAt(profileIndex);
|
||||
}
|
||||
qDebug("configured profile: %s", qPrintable(selectedProfileName));
|
||||
qDebug("configured profile: %s", qPrintable(selectedProfileName));
|
||||
|
||||
// if we have a command line parameter, it is either a nxm link or
|
||||
// a binary to start
|
||||
if ((arguments.size() > 1) && (!isNxmLink(arguments.at(1)))) {
|
||||
QString exeName = arguments.at(1);
|
||||
qDebug("starting %s from command line", qPrintable(exeName));
|
||||
arguments.removeFirst(); // remove application name (ModOrganizer.exe)
|
||||
arguments.removeFirst(); // remove binary name
|
||||
// pass the remaining parameters to the binary
|
||||
mainWindow.spawnProgram(exeName, arguments.join(" "), selectedProfileName, QDir());
|
||||
return 0;
|
||||
}
|
||||
// if we have a command line parameter, it is either a nxm link or
|
||||
// a binary to start
|
||||
if ((arguments.size() > 1) && (!isNxmLink(arguments.at(1)))) {
|
||||
QString exeName = arguments.at(1);
|
||||
qDebug("starting %s from command line", qPrintable(exeName));
|
||||
arguments.removeFirst(); // remove application name (ModOrganizer.exe)
|
||||
arguments.removeFirst(); // remove binary name
|
||||
// pass the remaining parameters to the binary
|
||||
mainWindow.spawnProgram(exeName, arguments.join(" "), selectedProfileName, QDir());
|
||||
return 0;
|
||||
}
|
||||
|
||||
mainWindow.createFirstProfile();
|
||||
mainWindow.createFirstProfile();
|
||||
|
||||
if (selectedProfileName.length() != 0) {
|
||||
if (!mainWindow.setCurrentProfile(selectedProfileName)) {
|
||||
if (selectedProfileName.length() != 0) {
|
||||
if (!mainWindow.setCurrentProfile(selectedProfileName)) {
|
||||
mainWindow.setCurrentProfile(1);
|
||||
qWarning("failed to set profile: %s",
|
||||
selectedProfileName.toUtf8().constData());
|
||||
}
|
||||
} else {
|
||||
mainWindow.setCurrentProfile(1);
|
||||
qWarning("failed to set profile: %s",
|
||||
selectedProfileName.toUtf8().constData());
|
||||
}
|
||||
} else {
|
||||
mainWindow.setCurrentProfile(1);
|
||||
}
|
||||
|
||||
qDebug("displaying main window");
|
||||
mainWindow.show();
|
||||
qDebug("displaying main window");
|
||||
mainWindow.show();
|
||||
|
||||
if ((arguments.size() > 1) &&
|
||||
(isNxmLink(arguments.at(1)))) {
|
||||
qDebug("starting download from command line: %s", qPrintable(arguments.at(1)));
|
||||
mainWindow.externalMessage(arguments.at(1));
|
||||
if ((arguments.size() > 1) &&
|
||||
(isNxmLink(arguments.at(1)))) {
|
||||
qDebug("starting download from command line: %s", qPrintable(arguments.at(1)));
|
||||
mainWindow.externalMessage(arguments.at(1));
|
||||
}
|
||||
splash.finish(&mainWindow);
|
||||
res = application.exec();
|
||||
}
|
||||
splash.finish(&mainWindow);
|
||||
return application.exec();
|
||||
return res;
|
||||
} catch (const std::exception &e) {
|
||||
reportError(e.what());
|
||||
return 1;
|
||||
|
||||
+174
-39
@@ -98,6 +98,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QNetworkInterface>
|
||||
#include <QNetworkProxy>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QCoreApplication>
|
||||
|
||||
|
||||
#ifdef TEST_MODELS
|
||||
@@ -138,8 +139,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
: QMainWindow(parent), ui(new Ui::MainWindow), m_Tutorial(this, "MainWindow"),
|
||||
m_ExeName(exeName), m_OldProfileIndex(-1),
|
||||
m_DirectoryStructure(new DirectoryEntry(L"data", NULL, 0)),
|
||||
m_ModList(NexusInterface::instance()), m_ModListGroupingProxy(NULL), m_ModListSortProxy(NULL),
|
||||
m_OldExecutableIndex(-1), m_GamePath(ToQString(GameInfo::instance().getGameDirectory())),
|
||||
m_ModList(this), m_ModListGroupingProxy(NULL), m_ModListSortProxy(NULL),
|
||||
m_PluginList(this), m_OldExecutableIndex(-1), m_GamePath(ToQString(GameInfo::instance().getGameDirectory())),
|
||||
m_DownloadManager(NexusInterface::instance(), this),
|
||||
m_InstallationManager(this), m_Translator(NULL), m_TranslatorQt(NULL),
|
||||
m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()),
|
||||
@@ -148,8 +149,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
m_GameInfo(new GameInfoImpl())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
this->setWindowTitle(ToQString(GameInfo::instance().getGameName()).append(" Mod Organizer v").append(m_Updater.getVersion().canonicalString()));
|
||||
this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_Updater.getVersion().displayString());
|
||||
|
||||
m_RefreshProgress = new QProgressBar(statusBar());
|
||||
m_RefreshProgress->setTextVisible(true);
|
||||
@@ -233,6 +233,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), this, SLOT(modlistChanged(QModelIndex, int)));
|
||||
connect(&m_ModList, SIGNAL(removeSelectedMods()), this, SLOT(removeMod_clicked()));
|
||||
connect(&m_ModList, SIGNAL(requestColumnSelect(QPoint)), this, SLOT(displayColumnSelection(QPoint)));
|
||||
connect(&m_ModList, SIGNAL(fileMoved(QString, QString, QString)), this, SLOT(fileMoved(QString, QString, QString)));
|
||||
connect(ui->modList, SIGNAL(dropModeUpdate(bool)), &m_ModList, SLOT(dropModeUpdate(bool)));
|
||||
connect(m_ModListSortProxy, SIGNAL(filterActive(bool)), this, SLOT(modFilterActive(bool)));
|
||||
connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString)));
|
||||
@@ -254,7 +255,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
connect(&m_Updater, SIGNAL(updateAvailable()), this, SLOT(updateAvailable()));
|
||||
connect(&m_Updater, SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString)));
|
||||
|
||||
connect(ExitProxy::instance(), SIGNAL(exit()), this, SLOT(close()));
|
||||
// connect(ExitProxy::instance(), SIGNAL(exit()), this, SLOT(close()));
|
||||
|
||||
connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool)));
|
||||
connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
|
||||
@@ -411,7 +412,7 @@ void MainWindow::actionToToolButton(QAction *&sourceAction)
|
||||
button->setToolButtonStyle(ui->toolBar->toolButtonStyle());
|
||||
button->setToolTip(sourceAction->toolTip());
|
||||
button->setShortcut(sourceAction->shortcut());
|
||||
QMenu *buttonMenu = new QMenu(sourceAction->text());
|
||||
QMenu *buttonMenu = new QMenu(sourceAction->text(), button);
|
||||
button->setMenu(buttonMenu);
|
||||
QAction *newAction = ui->toolBar->insertWidget(sourceAction, button);
|
||||
newAction->setObjectName(sourceAction->objectName());
|
||||
@@ -997,6 +998,7 @@ bool MainWindow::registerPlugin(QObject *plugin)
|
||||
{ // proxy plugins
|
||||
IPluginProxy *proxy = qobject_cast<IPluginProxy*>(plugin);
|
||||
if (verifyPlugin(proxy)) {
|
||||
proxy->setParentWidget(this);
|
||||
QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()));
|
||||
foreach (const QString &pluginName, pluginNames) {
|
||||
try {
|
||||
@@ -1040,11 +1042,38 @@ void MainWindow::loadPlugins()
|
||||
registerPlugin(plugin);
|
||||
}
|
||||
|
||||
QFile loadCheck(QCoreApplication::applicationDirPath() + "/plugin_loadcheck.tmp");
|
||||
if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) {
|
||||
// oh, there was a failed plugin load last time. Find out which plugin was loaded last
|
||||
QString fileName;
|
||||
while (!loadCheck.atEnd()) {
|
||||
fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed();
|
||||
}
|
||||
if (QMessageBox::question(this, tr("Plugin error"),
|
||||
tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n"
|
||||
"(Please note: If this is the first time you see this message for this plugin you may want to give it another try. "
|
||||
"The plugin may be able to recover from the problem)").arg(fileName),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
|
||||
m_Settings.addBlacklistPlugin(fileName);
|
||||
}
|
||||
loadCheck.close();
|
||||
}
|
||||
|
||||
loadCheck.open(QIODevice::WriteOnly);
|
||||
|
||||
QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
|
||||
qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData());
|
||||
QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
if (m_Settings.pluginBlacklisted(iter.fileName())) {
|
||||
qDebug("plugin \"%s\" blacklisted", qPrintable(iter.fileName()));
|
||||
continue;
|
||||
}
|
||||
loadCheck.write(iter.fileName().toUtf8());
|
||||
loadCheck.write("\n");
|
||||
loadCheck.flush();
|
||||
QString pluginName = iter.filePath();
|
||||
if (QLibrary::isLibrary(pluginName)) {
|
||||
QPluginLoader pluginLoader(pluginName);
|
||||
@@ -1063,6 +1092,9 @@ void MainWindow::loadPlugins()
|
||||
}
|
||||
}
|
||||
|
||||
// remove the load check file on success
|
||||
loadCheck.remove();
|
||||
|
||||
m_DownloadManager.setSupportedExtensions(m_InstallationManager.getSupportedExtensions());
|
||||
|
||||
m_DiagnosisPlugins.push_back(this);
|
||||
@@ -1172,6 +1204,21 @@ QVariant MainWindow::pluginSetting(const QString &pluginName, const QString &key
|
||||
return m_Settings.pluginSetting(pluginName, key);
|
||||
}
|
||||
|
||||
void MainWindow::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value)
|
||||
{
|
||||
m_Settings.setPluginSetting(pluginName, key, value);
|
||||
}
|
||||
|
||||
QVariant MainWindow::persistent(const QString &pluginName, const QString &key, const QVariant &def) const
|
||||
{
|
||||
return m_Settings.pluginPersistent(pluginName, key, def);
|
||||
}
|
||||
|
||||
void MainWindow::setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync)
|
||||
{
|
||||
m_Settings.setPluginPersistent(pluginName, key, value, sync);
|
||||
}
|
||||
|
||||
QString MainWindow::pluginDataPath() const
|
||||
{
|
||||
QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
|
||||
@@ -1224,6 +1271,11 @@ HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arg
|
||||
}
|
||||
}
|
||||
|
||||
while (m_RefreshProgress->isVisible()) {
|
||||
::Sleep(1000);
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
return startBinary(binary, arguments, profileName, m_Settings.logLevel(), currentDirectory, true);
|
||||
}
|
||||
|
||||
@@ -1273,12 +1325,11 @@ void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments,
|
||||
|
||||
this->setEnabled(true);
|
||||
refreshDirectoryStructure();
|
||||
refreshDataTree();
|
||||
if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
|
||||
QFile::remove(m_CurrentProfile->getLoadOrderFileName());
|
||||
}
|
||||
refreshLists();
|
||||
dialog->hide();
|
||||
dialog->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1448,6 +1499,8 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director
|
||||
updateTo(directoryChild, temp.str(), **current, conflictsOnly);
|
||||
if (directoryChild->childCount() != 0) {
|
||||
subTree->addChild(directoryChild);
|
||||
} else {
|
||||
delete directoryChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1622,11 +1675,15 @@ void MainWindow::refreshESPList()
|
||||
m_CurrentProfile->writeModlist();
|
||||
|
||||
// clear list
|
||||
m_PluginList.refresh(m_CurrentProfile->getName(),
|
||||
*m_DirectoryStructure,
|
||||
m_CurrentProfile->getPluginsFileName(),
|
||||
m_CurrentProfile->getLoadOrderFileName(),
|
||||
m_CurrentProfile->getLockedOrderFileName());
|
||||
try {
|
||||
m_PluginList.refresh(m_CurrentProfile->getName(),
|
||||
*m_DirectoryStructure,
|
||||
m_CurrentProfile->getPluginsFileName(),
|
||||
m_CurrentProfile->getLoadOrderFileName(),
|
||||
m_CurrentProfile->getLockedOrderFileName());
|
||||
} catch (const std::exception &e) {
|
||||
reportError(tr("Failed to refresh list of esps: %s").arg(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1926,7 +1983,6 @@ void MainWindow::on_btnRefreshData_clicked()
|
||||
{
|
||||
if (!m_DirectoryUpdate) {
|
||||
refreshDirectoryStructure();
|
||||
refreshDataTree();
|
||||
} else {
|
||||
qDebug("directory update");
|
||||
}
|
||||
@@ -1950,6 +2006,10 @@ void MainWindow::on_tabWidget_currentChanged(int index)
|
||||
|
||||
void MainWindow::installMod(const QString &fileName)
|
||||
{
|
||||
if (m_CurrentProfile == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasIniTweaks = false;
|
||||
GuessedValue<QString> modName;
|
||||
m_CurrentProfile->writeModlistNow();
|
||||
@@ -2329,10 +2389,16 @@ void MainWindow::refresher_progress(int percent)
|
||||
|
||||
void MainWindow::directory_refreshed()
|
||||
{
|
||||
statusBar()->hide();
|
||||
|
||||
DirectoryEntry *newStructure = m_DirectoryRefresher.getDirectoryStructure();
|
||||
if (newStructure != NULL) {
|
||||
delete m_DirectoryStructure;
|
||||
DirectoryEntry *oldStructure = m_DirectoryStructure;
|
||||
m_DirectoryStructure = newStructure;
|
||||
delete oldStructure;
|
||||
|
||||
refreshDataTree();
|
||||
refreshLists();
|
||||
} else {
|
||||
// TODO: don't know why this happens, this slot seems to get called twice with only one emit
|
||||
return;
|
||||
@@ -2342,7 +2408,6 @@ void MainWindow::directory_refreshed()
|
||||
refreshLists();
|
||||
}
|
||||
// m_RefreshProgress->setVisible(false);
|
||||
statusBar()->hide();
|
||||
|
||||
// some problem-reports may rely on the virtual directory tree so they need to be updated
|
||||
// now
|
||||
@@ -2541,6 +2606,29 @@ void MainWindow::modlistChanged(int)
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName)
|
||||
{
|
||||
const FileEntry::Ptr filePtr = m_DirectoryStructure->findFile(ToWString(filePath));
|
||||
if (filePtr.get() != NULL) {
|
||||
try {
|
||||
FilesOrigin &oldOrigin = m_DirectoryStructure->getOriginByName(ToWString(oldOriginName));
|
||||
FilesOrigin &newOrigin = m_DirectoryStructure->getOriginByName(ToWString(newOriginName));
|
||||
|
||||
QString fullNewPath = ToQString(newOrigin.getPath()) + "\\" + filePath;
|
||||
WIN32_FIND_DATAW findData;
|
||||
::FindFirstFileW(ToWString(fullNewPath).c_str(), &findData);
|
||||
|
||||
filePtr->addOrigin(newOrigin.getID(), findData.ftCreationTime, L"");
|
||||
filePtr->removeOrigin(oldOrigin.getID());
|
||||
} catch (const std::exception &e) {
|
||||
reportError(tr("Failed to move \"%1\" from mod \"%2\" to \"%3\": %4").arg(filePath).arg(oldOriginName).arg(newOriginName).arg(e.what()));
|
||||
}
|
||||
} else {
|
||||
// this is probably not an error, the specified path is likely a directory
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QTreeWidgetItem *MainWindow::addFilterItem(QTreeWidgetItem *root, const QString &name, int categoryID)
|
||||
{
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(name));
|
||||
@@ -2795,6 +2883,15 @@ void MainWindow::unendorse_clicked()
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::overwriteClosed(int)
|
||||
{
|
||||
QDialog *dialog = this->findChild<QDialog*>("__overwriteDialog");
|
||||
if (dialog != NULL) {
|
||||
dialog->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab)
|
||||
{
|
||||
std::vector<ModInfo::EFlag> flags = modInfo->getFlags();
|
||||
@@ -2807,6 +2904,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index,
|
||||
dialog->show();
|
||||
dialog->raise();
|
||||
dialog->activateWindow();
|
||||
connect(dialog, SIGNAL(finished(int)), this, SLOT(overwriteClosed(int)));
|
||||
} else {
|
||||
ModInfoDialog dialog(modInfo, m_DirectoryStructure, this);
|
||||
connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString)));
|
||||
@@ -2974,7 +3072,6 @@ void MainWindow::openExplorer_clicked()
|
||||
::ShellExecuteW(NULL, L"explore", ToWString(modInfo->absolutePath()).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::information_clicked()
|
||||
{
|
||||
try {
|
||||
@@ -2984,7 +3081,6 @@ void MainWindow::information_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::syncOverwrite()
|
||||
{
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
|
||||
@@ -2996,7 +3092,6 @@ void MainWindow::syncOverwrite()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::createModFromOverwrite()
|
||||
{
|
||||
GuessedValue<QString> name;
|
||||
@@ -3024,20 +3119,18 @@ void MainWindow::createModFromOverwrite()
|
||||
}
|
||||
|
||||
ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(m_ContextRow);
|
||||
|
||||
shellMove(QStringList(overwriteInfo->absolutePath() + "\\*"), QStringList(newMod->absolutePath()), this);
|
||||
shellMove(QStringList(QDir::toNativeSeparators(overwriteInfo->absolutePath()) + "\\*"),
|
||||
QStringList(QDir::toNativeSeparators(newMod->absolutePath())), this);
|
||||
|
||||
refreshModList();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::cancelModListEditor()
|
||||
{
|
||||
ui->modList->setEnabled(false);
|
||||
ui->modList->setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_modList_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
@@ -3060,7 +3153,6 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MainWindow::addCategories(QMenu *menu, int targetID)
|
||||
{
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
|
||||
@@ -3099,7 +3191,6 @@ bool MainWindow::addCategories(QMenu *menu, int targetID)
|
||||
return childEnabled;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::saveCategoriesFromMenu(QMenu *menu, int modRow)
|
||||
{
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(modRow);
|
||||
@@ -3116,7 +3207,6 @@ void MainWindow::saveCategoriesFromMenu(QMenu *menu, int modRow)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::saveCategories()
|
||||
{
|
||||
QMenu *menu = qobject_cast<QMenu*>(sender());
|
||||
@@ -3160,8 +3250,6 @@ void MainWindow::saveCategories()
|
||||
refreshFilters();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MainWindow::savePrimaryCategory()
|
||||
{
|
||||
QMenu *menu = qobject_cast<QMenu*>(sender());
|
||||
@@ -3186,7 +3274,6 @@ void MainWindow::savePrimaryCategory()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::checkModsForUpdates()
|
||||
{
|
||||
statusBar()->show();
|
||||
@@ -3204,6 +3291,45 @@ void MainWindow::checkModsForUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::changeVersioningScheme() {
|
||||
if (QMessageBox::question(this, tr("Continue?"),
|
||||
tr("The versioning scheme decides which version is considered newer than another.\n"
|
||||
"This function will guess the versioning scheme under the assumption that the installed version is outdated."),
|
||||
QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Yes) {
|
||||
|
||||
ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
|
||||
|
||||
bool success = false;
|
||||
|
||||
static VersionInfo::VersionScheme schemes[] = { VersionInfo::SCHEME_REGULAR, VersionInfo::SCHEME_DECIMALMARK, VersionInfo::SCHEME_NUMBERSANDLETTERS };
|
||||
|
||||
for (int i = 0; i < sizeof(schemes) / sizeof(VersionInfo::VersionScheme) && !success; ++i) {
|
||||
VersionInfo verOld(info->getVersion().canonicalString(), schemes[i]);
|
||||
VersionInfo verNew(info->getNewestVersion().canonicalString(), schemes[i]);
|
||||
if (verOld < verNew) {
|
||||
info->setVersion(verOld);
|
||||
info->setNewestVersion(verNew);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
QMessageBox::information(this, tr("Sorry"),
|
||||
tr("I don't know a versioning scheme where %1 is newer than %2.").arg(info->getNewestVersion().canonicalString()).arg(info->getVersion().canonicalString()),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::ignoreUpdate() {
|
||||
ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
|
||||
info->ignoreUpdate(true);
|
||||
}
|
||||
|
||||
void MainWindow::unignoreUpdate()
|
||||
{
|
||||
ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
|
||||
info->ignoreUpdate(false);
|
||||
}
|
||||
|
||||
void MainWindow::addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInfo::Ptr info)
|
||||
{
|
||||
@@ -3225,7 +3351,6 @@ void MainWindow::addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInf
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::addPrimaryCategoryCandidates()
|
||||
{
|
||||
QMenu *menu = qobject_cast<QMenu*>(sender());
|
||||
@@ -3239,7 +3364,6 @@ void MainWindow::addPrimaryCategoryCandidates()
|
||||
addPrimaryCategoryCandidates(menu, modInfo);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::enableVisibleMods()
|
||||
{
|
||||
if (QMessageBox::question(NULL, tr("Confirm"), tr("Really enable all visible mods?"),
|
||||
@@ -3248,7 +3372,6 @@ void MainWindow::enableVisibleMods()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::disableVisibleMods()
|
||||
{
|
||||
if (QMessageBox::question(NULL, tr("Confirm"), tr("Really disable all visible mods?"),
|
||||
@@ -3257,7 +3380,6 @@ void MainWindow::disableVisibleMods()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::exportModListCSV()
|
||||
{
|
||||
SelectionDialog selection(tr("Choose what to export"));
|
||||
@@ -3312,7 +3434,6 @@ void MainWindow::exportModListCSV()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void addMenuAsPushButton(QMenu *menu, QMenu *subMenu)
|
||||
{
|
||||
QPushButton *pushBtn = new QPushButton(subMenu->title());
|
||||
@@ -3322,13 +3443,13 @@ void addMenuAsPushButton(QMenu *menu, QMenu *subMenu)
|
||||
menu->addAction(action);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
try {
|
||||
QTreeView *modList = findChild<QTreeView*>("modList");
|
||||
|
||||
m_ContextRow = mapToModel(&m_ModList, modList->indexAt(pos)).row();
|
||||
QModelIndex index = mapToModel(&m_ModList, modList->indexAt(pos));
|
||||
m_ContextRow = index.row();
|
||||
|
||||
QMenu menu;
|
||||
|
||||
@@ -3367,6 +3488,19 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
|
||||
connect(primaryCategoryMenu, SIGNAL(aboutToHide()), this, SLOT(savePrimaryCategory()));
|
||||
addMenuAsPushButton(&menu, primaryCategoryMenu);
|
||||
|
||||
menu.addSeparator();
|
||||
if (info->downgradeAvailable()) {
|
||||
menu.addAction(tr("Change versioning scheme"), this, SLOT(changeVersioningScheme()));
|
||||
}
|
||||
if (info->updateAvailable() || info->downgradeAvailable()) {
|
||||
if (info->updateIgnored()) {
|
||||
menu.addAction(tr("Un-ignore update"), this, SLOT(unignoreUpdate()));
|
||||
} else {
|
||||
menu.addAction(tr("Ignore update"), this, SLOT(ignoreUpdate()));
|
||||
}
|
||||
}
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(tr("Rename Mod..."), this, SLOT(renameMod_clicked()));
|
||||
menu.addAction(tr("Remove Mod..."), this, SLOT(removeMod_clicked()));
|
||||
menu.addAction(tr("Reinstall Mod"), this, SLOT(reinstallMod_clicked()));
|
||||
@@ -4094,6 +4228,7 @@ void MainWindow::on_actionUpdate_triggered()
|
||||
(m_AskForNexusPW && queryLogin(username, password)))) {
|
||||
NexusInterface::instance()->getAccessManager()->login(username, password);
|
||||
m_LoginAttempted = true;
|
||||
m_PostLoginTasks.push_back([&](MainWindow*) { m_Updater.startUpdate(); });
|
||||
} else {
|
||||
m_Updater.startUpdate();
|
||||
}
|
||||
@@ -4113,9 +4248,9 @@ void MainWindow::on_actionEndorseMO_triggered()
|
||||
void MainWindow::updateDownloadListDelegate()
|
||||
{
|
||||
if (ui->compactBox->isChecked()) {
|
||||
ui->downloadView->setItemDelegate(new DownloadListWidgetCompactDelegate(&m_DownloadManager, ui->downloadView));
|
||||
ui->downloadView->setItemDelegate(new DownloadListWidgetCompactDelegate(&m_DownloadManager, ui->downloadView, ui->downloadView));
|
||||
} else {
|
||||
ui->downloadView->setItemDelegate(new DownloadListWidgetDelegate(&m_DownloadManager, ui->downloadView));
|
||||
ui->downloadView->setItemDelegate(new DownloadListWidgetDelegate(&m_DownloadManager, ui->downloadView, ui->downloadView));
|
||||
}
|
||||
|
||||
DownloadListSortProxy *sortProxy = new DownloadListSortProxy(&m_DownloadManager, ui->downloadView);
|
||||
@@ -4173,7 +4308,7 @@ void MainWindow::nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant us
|
||||
} else {
|
||||
std::vector<ModInfo::Ptr> info = ModInfo::getByModID(result["id"].toInt());
|
||||
for (auto iter = info.begin(); iter != info.end(); ++iter) {
|
||||
(*iter)->setNewestVersion(VersionInfo(result["version"].toString()));
|
||||
(*iter)->setNewestVersion(result["version"].toString());
|
||||
(*iter)->setNexusDescription(result["description"].toString());
|
||||
if (NexusInterface::instance()->getAccessManager()->loggedIn() &&
|
||||
result.contains("voted_by_user")) {
|
||||
|
||||
@@ -105,6 +105,9 @@ public:
|
||||
virtual bool removeMod(MOBase::IModInterface *mod);
|
||||
virtual void modDataChanged(MOBase::IModInterface *mod);
|
||||
virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const;
|
||||
virtual void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value);
|
||||
virtual QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def = QVariant()) const;
|
||||
virtual void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync = true);
|
||||
virtual QString pluginDataPath() const;
|
||||
virtual void installMod(const QString &fileName);
|
||||
virtual QString resolvePath(const QString &fileName) const;
|
||||
@@ -315,6 +318,8 @@ private:
|
||||
std::vector<MOBase::IPluginDiagnose*> m_DiagnosisPlugins;
|
||||
std::vector<QString> m_UnloadedPlugins;
|
||||
|
||||
QFile m_PluginsCheck;
|
||||
|
||||
private slots:
|
||||
|
||||
void showMessage(const QString &message);
|
||||
@@ -435,6 +440,7 @@ private slots:
|
||||
void updateStyle(const QString &style);
|
||||
|
||||
void modlistChanged(const QModelIndex &index, int role);
|
||||
void fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName);
|
||||
|
||||
void savePluginList();
|
||||
|
||||
@@ -458,6 +464,11 @@ private slots:
|
||||
|
||||
void toolBar_customContextMenuRequested(const QPoint &point);
|
||||
void removeFromToolbar();
|
||||
void overwriteClosed(int);
|
||||
|
||||
void changeVersioningScheme();
|
||||
void ignoreUpdate();
|
||||
void unignoreUpdate();
|
||||
|
||||
private slots: // ui slots
|
||||
// actions
|
||||
|
||||
+1
-1
@@ -786,7 +786,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
|
||||
<item>
|
||||
<widget class="QLabel" name="bsaWarning">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Marked Archives (<img src=":/MO/gui/resources/dialog-warning_16.png"/>) are still loaded on Skyrim but the <a href="http://forums.bethsoft.com/topic/1354395-update-bsas-and-you/"><span style=" text-decoration: underline; color:#0000ff;">regular file override</span></a> mechanism will apply: Loose files override BSAs, no matter the mod/plugin priority.</p></body></html></string>
|
||||
<string><html><head/><body><p>Marked Archives (<img src=":/MO/gui/warning_16"/>) are still loaded on Skyrim but the <a href="http://forums.bethsoft.com/topic/1354395-update-bsas-and-you/"><span style=" text-decoration: underline; color:#0000ff;">regular file override</span></a> mechanism will apply: Loose files override BSAs, no matter the mod/plugin priority.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
||||
+45
-26
@@ -303,10 +303,11 @@ ModInfoRegular::ModInfoRegular(const QDir &path, DirectoryEntry **directoryStruc
|
||||
QString metaFileName = path.absoluteFilePath("meta.ini");
|
||||
QSettings metaFile(metaFileName, QSettings::IniFormat);
|
||||
|
||||
m_Notes = metaFile.value("notes", "").toString();
|
||||
m_NexusID = metaFile.value("modid", -1).toInt();
|
||||
m_Notes = metaFile.value("notes", "").toString();
|
||||
m_NexusID = metaFile.value("modid", -1).toInt();
|
||||
m_Version.parse(metaFile.value("version", "").toString());
|
||||
m_NewestVersion = metaFile.value("newestVersion", "").toString();
|
||||
m_NewestVersion = metaFile.value("newestVersion", "").toString();
|
||||
m_IgnoredVersion = metaFile.value("ignoredVersion", "").toString();
|
||||
m_InstallationFile = metaFile.value("installationFile", "").toString();
|
||||
m_NexusDescription = metaFile.value("nexusDescription", "").toString();
|
||||
m_LastNexusQuery = QDateTime::fromString(metaFile.value("lastNexusQuery", "").toString(), Qt::ISODate);
|
||||
@@ -350,8 +351,6 @@ ModInfoRegular::ModInfoRegular(const QDir &path, DirectoryEntry **directoryStruc
|
||||
ModInfoRegular::~ModInfoRegular()
|
||||
{
|
||||
try {
|
||||
//TODO this may cause the meta-file and the directory to be
|
||||
// re-created after a remove
|
||||
saveMeta();
|
||||
} catch (const std::exception &e) {
|
||||
qCritical("failed to save meta information for \"%s\": %s",
|
||||
@@ -371,28 +370,26 @@ bool ModInfoRegular::isEmpty() const
|
||||
|
||||
void ModInfoRegular::saveMeta()
|
||||
{
|
||||
if (m_MetaInfoChanged) {
|
||||
if (QFile::exists(absolutePath().append("/meta.ini"))) {
|
||||
QSettings metaFile(absolutePath().append("/meta.ini"), QSettings::IniFormat);
|
||||
if (metaFile.status() == QSettings::NoError) {
|
||||
std::set<int> temp = m_Categories;
|
||||
temp.erase(m_PrimaryCategory);
|
||||
metaFile.setValue("category", QString("%1").arg(m_PrimaryCategory) + "," + SetJoin(temp, ","));
|
||||
metaFile.setValue("newestVersion", m_NewestVersion.canonicalString());
|
||||
metaFile.setValue("version", m_Version.canonicalString());
|
||||
metaFile.setValue("modid", m_NexusID);
|
||||
metaFile.setValue("notes", m_Notes);
|
||||
metaFile.setValue("nexusDescription", m_NexusDescription);
|
||||
metaFile.setValue("lastNexusQuery", m_LastNexusQuery.toString(Qt::ISODate));
|
||||
if (m_EndorsedState != ENDORSED_UNKNOWN) {
|
||||
metaFile.setValue("endorsed", m_EndorsedState);
|
||||
}
|
||||
|
||||
} else {
|
||||
reportError(tr("failed to write %1/meta.ini: %2").arg(absolutePath()).arg(metaFile.status()));
|
||||
// only write meta data if the mod directory exists
|
||||
if (m_MetaInfoChanged && QFile::exists(absolutePath())) {
|
||||
QSettings metaFile(absolutePath().append("/meta.ini"), QSettings::IniFormat);
|
||||
if (metaFile.status() == QSettings::NoError) {
|
||||
std::set<int> temp = m_Categories;
|
||||
temp.erase(m_PrimaryCategory);
|
||||
metaFile.setValue("category", QString("%1").arg(m_PrimaryCategory) + "," + SetJoin(temp, ","));
|
||||
metaFile.setValue("newestVersion", m_NewestVersion.canonicalString());
|
||||
metaFile.setValue("ignoredVersion", m_IgnoredVersion.canonicalString());
|
||||
metaFile.setValue("version", m_Version.canonicalString());
|
||||
metaFile.setValue("modid", m_NexusID);
|
||||
metaFile.setValue("notes", m_Notes);
|
||||
metaFile.setValue("nexusDescription", m_NexusDescription);
|
||||
metaFile.setValue("lastNexusQuery", m_LastNexusQuery.toString(Qt::ISODate));
|
||||
if (m_EndorsedState != ENDORSED_UNKNOWN) {
|
||||
metaFile.setValue("endorsed", m_EndorsedState);
|
||||
}
|
||||
metaFile.sync(); // sync needs to be called to ensure the file is created
|
||||
} else {
|
||||
qWarning("mod %s has no meta.ini at %s/meta.ini", m_Name.toUtf8().constData(), absolutePath().toUtf8().constData());
|
||||
reportError(tr("failed to write %1/meta.ini: %2").arg(absolutePath()).arg(metaFile.status()));
|
||||
}
|
||||
m_MetaInfoChanged = false;
|
||||
}
|
||||
@@ -401,10 +398,22 @@ void ModInfoRegular::saveMeta()
|
||||
|
||||
bool ModInfoRegular::updateAvailable() const
|
||||
{
|
||||
if (m_IgnoredVersion.isValid() && (m_IgnoredVersion == m_NewestVersion)) {
|
||||
return false;
|
||||
}
|
||||
return m_NewestVersion.isValid() && (m_Version < m_NewestVersion);
|
||||
}
|
||||
|
||||
|
||||
bool ModInfoRegular::downgradeAvailable() const
|
||||
{
|
||||
if (m_IgnoredVersion.isValid() && (m_IgnoredVersion == m_NewestVersion)) {
|
||||
return false;
|
||||
}
|
||||
return m_NewestVersion.isValid() && (m_NewestVersion < m_Version);
|
||||
}
|
||||
|
||||
|
||||
void ModInfoRegular::nxmDescriptionAvailable(int, QVariant, QVariant resultData)
|
||||
{
|
||||
QVariantMap result = resultData.toMap();
|
||||
@@ -581,6 +590,16 @@ QString ModInfoRegular::absolutePath() const
|
||||
return m_Path;
|
||||
}
|
||||
|
||||
void ModInfoRegular::ignoreUpdate(bool ignore)
|
||||
{
|
||||
if (ignore) {
|
||||
m_IgnoredVersion = m_NewestVersion;
|
||||
} else {
|
||||
m_IgnoredVersion.clear();
|
||||
}
|
||||
m_MetaInfoChanged = true;
|
||||
}
|
||||
|
||||
|
||||
std::vector<ModInfo::EFlag> ModInfoRegular::getFlags() const
|
||||
{
|
||||
@@ -792,9 +811,9 @@ ModInfoBackup::ModInfoBackup(const QDir &path, DirectoryEntry **directoryStructu
|
||||
|
||||
|
||||
ModInfoOverwrite::ModInfoOverwrite()
|
||||
: m_StartupTime(QDateTime::currentDateTime())
|
||||
{
|
||||
testValid();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+54
-1
@@ -192,6 +192,22 @@ public:
|
||||
**/
|
||||
virtual bool updateAvailable() const = 0;
|
||||
|
||||
/**
|
||||
* @return true if the update currently available is ignored
|
||||
*/
|
||||
virtual bool updateIgnored() const = 0;
|
||||
|
||||
/**
|
||||
* @brief test if the "newest" version of the mod is older than the installed version
|
||||
*
|
||||
* test if there is a newer version of the mod. This does NOT cause
|
||||
* information to be retrieved from the nexus, it will only test version information already
|
||||
* available locally. Use checkAllForUpdate() to update this version information
|
||||
*
|
||||
* @return true if the newest version is older than the installed one
|
||||
**/
|
||||
virtual bool downgradeAvailable() const = 0;
|
||||
|
||||
/**
|
||||
* @brief request an update of nexus description for this mod.
|
||||
*
|
||||
@@ -309,6 +325,11 @@ public:
|
||||
**/
|
||||
virtual MOBase::VersionInfo getNewestVersion() const = 0;
|
||||
|
||||
/**
|
||||
* @brief ignore the newest version for updates
|
||||
*/
|
||||
virtual void ignoreUpdate(bool ignore) = 0;
|
||||
|
||||
/**
|
||||
* @brief getter for the nexus mod id
|
||||
*
|
||||
@@ -494,6 +515,22 @@ public:
|
||||
**/
|
||||
bool updateAvailable() const;
|
||||
|
||||
/**
|
||||
* @return true if the current update is being ignored
|
||||
*/
|
||||
virtual bool updateIgnored() const { return m_IgnoredVersion == m_NewestVersion; }
|
||||
|
||||
/**
|
||||
* @brief test if there is a newer version of the mod
|
||||
*
|
||||
* test if there is a newer version of the mod. This does NOT cause
|
||||
* information to be retrieved from the nexus, it will only test version information already
|
||||
* available locally. Use checkAllForUpdate() to update this version information
|
||||
*
|
||||
* @return true if there is a newer version
|
||||
**/
|
||||
bool downgradeAvailable() const;
|
||||
|
||||
/**
|
||||
* @brief request an update of nexus description for this mod.
|
||||
*
|
||||
@@ -620,6 +657,11 @@ public:
|
||||
**/
|
||||
MOBase::VersionInfo getNewestVersion() const { return m_NewestVersion; }
|
||||
|
||||
/**
|
||||
* @brief ignore the newest version for updates
|
||||
*/
|
||||
void ignoreUpdate(bool ignore);
|
||||
|
||||
/**
|
||||
* @brief getter for the installation file
|
||||
*
|
||||
@@ -746,6 +788,7 @@ private:
|
||||
|
||||
bool m_MetaInfoChanged;
|
||||
MOBase::VersionInfo m_NewestVersion;
|
||||
MOBase::VersionInfo m_IgnoredVersion;
|
||||
|
||||
EEndorsedState m_EndorsedState;
|
||||
|
||||
@@ -767,10 +810,13 @@ class ModInfoBackup : public ModInfoRegular
|
||||
public:
|
||||
|
||||
virtual bool updateAvailable() const { return false; }
|
||||
virtual bool updateIgnored() const { return false; }
|
||||
virtual bool downgradeAvailable() const { return false; }
|
||||
virtual bool updateNXMInfo() { return false; }
|
||||
virtual void setNexusID(int) {}
|
||||
virtual void endorse(bool) {}
|
||||
virtual int getFixedPriority() const { return -1; }
|
||||
virtual void ignoreUpdate(bool) {}
|
||||
virtual bool canBeUpdated() const { return false; }
|
||||
virtual bool canBeEnabled() const { return false; }
|
||||
virtual std::vector<QString> getIniTweaks() const { return std::vector<QString>(); }
|
||||
@@ -798,12 +844,15 @@ class ModInfoOverwrite : public ModInfo
|
||||
public:
|
||||
|
||||
virtual bool updateAvailable() const { return false; }
|
||||
virtual bool updateIgnored() const { return false; }
|
||||
virtual bool downgradeAvailable() const { return false; }
|
||||
virtual bool updateNXMInfo() { return false; }
|
||||
virtual void setCategory(int, bool) {}
|
||||
virtual bool setName(const QString&) { return false; }
|
||||
virtual void setNotes(const QString&) {}
|
||||
virtual void setNexusID(int) {}
|
||||
virtual void setNewestVersion(const MOBase::VersionInfo&) {}
|
||||
virtual void ignoreUpdate(bool) {}
|
||||
virtual void setNexusDescription(const QString&) {}
|
||||
virtual void setIsEndorsed(bool) {}
|
||||
virtual void setNeverEndorse() {}
|
||||
@@ -811,7 +860,7 @@ public:
|
||||
virtual void endorse(bool) {}
|
||||
virtual QString name() const { return "Overwrite"; }
|
||||
virtual QString notes() const { return ""; }
|
||||
virtual QDateTime creationTime() const { return QDateTime::currentDateTime(); }
|
||||
virtual QDateTime creationTime() const { return m_StartupTime; }
|
||||
virtual QString absolutePath() const;
|
||||
virtual MOBase::VersionInfo getNewestVersion() const { return ""; }
|
||||
virtual QString getInstallationFile() const { return ""; }
|
||||
@@ -828,6 +877,10 @@ private:
|
||||
|
||||
ModInfoOverwrite();
|
||||
|
||||
private:
|
||||
|
||||
QDateTime m_StartupTime;
|
||||
|
||||
};
|
||||
|
||||
#endif // MODINFO_H
|
||||
|
||||
@@ -76,7 +76,6 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
|
||||
m_UTF8Codec = QTextCodec::codecForName("utf-8");
|
||||
|
||||
QListWidget *textFileList = findChild<QListWidget*>("textFileList");
|
||||
QListWidget *iniFileList = findChild<QListWidget*>("iniFileList");
|
||||
QListWidget *iniTweaksList = findChild<QListWidget*>("iniTweaksList");
|
||||
QListWidget *activeESPList = findChild<QListWidget*>("activeESPList");
|
||||
QListWidget *inactiveESPList = findChild<QListWidget*>("inactiveESPList");
|
||||
@@ -707,7 +706,7 @@ QString ModInfoDialog::getFileCategory(int categoryID)
|
||||
void ModInfoDialog::updateVersionColor()
|
||||
{
|
||||
// QPalette versionColor;
|
||||
if (m_ModInfo->getVersion() < m_ModInfo->getNewestVersion()) {
|
||||
if (m_ModInfo->getVersion() != m_ModInfo->getNewestVersion()) {
|
||||
ui->versionEdit->setStyleSheet("color: red");
|
||||
// versionColor.setColor(QPalette::Text, Qt::red);
|
||||
ui->versionEdit->setToolTip(tr("Current Version: %1").arg(m_ModInfo->getNewestVersion().canonicalString()));
|
||||
@@ -758,13 +757,7 @@ void ModInfoDialog::modDetailsUpdated(bool success)
|
||||
ui->descriptionView->setHtml(tr("(description incomplete, please visit nexus)"));
|
||||
}
|
||||
|
||||
QString version = m_ModInfo->getNewestVersion().canonicalString();
|
||||
|
||||
if (!version.isEmpty()) {
|
||||
m_ModInfo->setNewestVersion(version);
|
||||
|
||||
updateVersionColor();
|
||||
}
|
||||
updateVersionColor();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-12
@@ -143,11 +143,12 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
|
||||
} else if (column == COL_NAME) {
|
||||
return modInfo->name();
|
||||
} else if (column == COL_VERSION) {
|
||||
QString version = modInfo->getVersion().canonicalString();
|
||||
if (version.isEmpty() && modInfo->canBeUpdated()) {
|
||||
version = "?";
|
||||
} else if (version[0] == 'd') {
|
||||
version.remove(0, 1);
|
||||
VersionInfo verInfo = modInfo->getVersion();
|
||||
QString version = verInfo.displayString();
|
||||
if (role != Qt::EditRole) {
|
||||
if (version.isEmpty() && modInfo->canBeUpdated()) {
|
||||
version = "?";
|
||||
}
|
||||
}
|
||||
return version;
|
||||
} else if (column == COL_PRIORITY) {
|
||||
@@ -241,17 +242,18 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
|
||||
result.setItalic(true);
|
||||
}
|
||||
} else if (column == COL_VERSION) {
|
||||
if (modInfo->updateAvailable()) {
|
||||
if (modInfo->updateAvailable() || modInfo->downgradeAvailable()) {
|
||||
result.setWeight(QFont::Bold);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
if (column == COL_VERSION) {
|
||||
if (modInfo->updateAvailable() &&
|
||||
modInfo->getNewestVersion().isValid()) {
|
||||
if (modInfo->updateAvailable()) {
|
||||
return QIcon(":/MO/gui/update_available");
|
||||
} else if (modInfo->getVersion().isVersionDate()) {
|
||||
} else if (modInfo->downgradeAvailable()) {
|
||||
return QIcon(":/MO/gui/warning");
|
||||
} else if (modInfo->getVersion().scheme() == VersionInfo::SCHEME_DATE) {
|
||||
return QIcon(":/MO/gui/version_date");
|
||||
}
|
||||
}
|
||||
@@ -264,7 +266,7 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
|
||||
} else if (column == COL_VERSION) {
|
||||
if (!modInfo->getNewestVersion().isValid()) {
|
||||
return QVariant();
|
||||
} else if (modInfo->updateAvailable()) {
|
||||
} else if (modInfo->updateAvailable() || modInfo->downgradeAvailable()) {
|
||||
return QBrush(Qt::red);
|
||||
} else {
|
||||
return QBrush(Qt::darkGreen);
|
||||
@@ -291,7 +293,13 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
|
||||
return QString();
|
||||
}
|
||||
} else if (column == COL_VERSION) {
|
||||
return tr("installed version: %1, newest version: %2").arg(modInfo->getVersion().canonicalString()).arg(modInfo->getNewestVersion().canonicalString());
|
||||
QString text = tr("installed version: %1, newest version: %2").arg(modInfo->getVersion().displayString()).arg(modInfo->getNewestVersion().displayString());
|
||||
if (modInfo->downgradeAvailable()) {
|
||||
text += "<br>" + tr("The newest version on Nexus seems to be older than the one you have installed. This could either mean the version you have has been withdrawn "
|
||||
"(i.e. due to a bug) or the author uses a non-standard versioning scheme and that newest version is actually newer. "
|
||||
"Either way you may want to \"upgrade\".");
|
||||
}
|
||||
return text;
|
||||
} else if (column == COL_CATEGORY) {
|
||||
const std::set<int> &categories = modInfo->getCategories();
|
||||
std::wostringstream categoryString;
|
||||
@@ -395,7 +403,8 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
} break;
|
||||
case COL_VERSION: {
|
||||
ModInfo::Ptr info = ModInfo::getByIndex(modID);
|
||||
VersionInfo version(value.toString());
|
||||
VersionInfo::VersionScheme scheme = info->getVersion().scheme();
|
||||
VersionInfo version(value.toString(), scheme);
|
||||
if (version.isValid()) {
|
||||
info->setVersion(version);
|
||||
return true;
|
||||
@@ -477,6 +486,7 @@ Qt::ItemFlags ModList::flags(const QModelIndex &modelIndex) const
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
QStringList ModList::mimeTypes() const
|
||||
{
|
||||
QStringList result = QAbstractItemModel::mimeTypes();
|
||||
@@ -544,6 +554,12 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa
|
||||
QDir modDirectory(modInfo->absolutePath());
|
||||
QDir gameDirectory(QDir::fromNativeSeparators(ToQString(MOShared::GameInfo::instance().getOverwriteDir())));
|
||||
|
||||
unsigned int overwriteIndex = ModInfo::findMod([](ModInfo::Ptr mod) -> bool {
|
||||
std::vector<ModInfo::EFlag> flags = mod->getFlags();
|
||||
return std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end(); });
|
||||
|
||||
QString overwriteName = ModInfo::getByIndex(overwriteIndex)->name();
|
||||
|
||||
foreach (const QUrl &url, mimeData->urls()) {
|
||||
QString relativePath = gameDirectory.relativeFilePath(url.toLocalFile());
|
||||
if (relativePath.startsWith("..")) {
|
||||
@@ -552,6 +568,7 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa
|
||||
}
|
||||
source.append(url.toLocalFile());
|
||||
target.append(modDirectory.absoluteFilePath(relativePath));
|
||||
emit fileMoved(relativePath, overwriteName, modInfo->name());
|
||||
}
|
||||
|
||||
if (source.count() != 0) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user