mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff78c6a014 | ||
|
|
340edcfbca | ||
|
|
c4f0bc39c7 | ||
|
|
e71c37df37 | ||
|
|
b32457a7d2 | ||
|
|
6e1e8c37eb | ||
|
|
469cc2d945 | ||
|
|
0e90b9d233 | ||
|
|
0e19c84722 | ||
|
|
daf4ae44fa | ||
|
|
ac29aa81f2 | ||
|
|
a0335d0a63 | ||
|
|
f1515193ca |
+14
-11
@@ -6,29 +6,31 @@ Requirements:
|
||||
|
||||
Visual C++ compiler 2010 (VC 10.0) or up
|
||||
- Included in visual c++ express 2010 or windows sdk 7.0
|
||||
Note: If you're having trouble installing the windows sdk, you may be affected by this bug: http://support.microsoft.com/kb/2717426
|
||||
|
||||
QtSDK 4.8.x (http://qt-project.org/downloads)
|
||||
- Qt5 is not yet supported but WIP
|
||||
- Install according to instruction
|
||||
|
||||
boost libraries (http://www.boost.org/)
|
||||
- Compile according to their instructions (using vc++)
|
||||
- As of time of writing boost_thread is the only compiled boost library used, you can
|
||||
disable the others to safe yourself the compile time
|
||||
- Compile according to their instructions (using vc++): http://www.boost.org/doc/libs/1_54_0/more/getting_started/windows.html
|
||||
- A few of the boost libraries need to be built (the rest is header-only). The only compiled lib MO needs (at the time of writing) is
|
||||
boost_thread. You can disable the others to safe yourself compile time (even on a modern system compiling boost can easily take an hour)
|
||||
|
||||
zlib (http://www.zlib.net/)
|
||||
- Compile static library according to their instructions
|
||||
- You should have a "zlibstatic.lib" under "build" afterwards
|
||||
- Depending on the version of zlib and how you built you should have a file called zlibstatic.lib or zlibstat.lib in "build" or "x86\ZLibStatRelease".
|
||||
- Please copy that lib file to "build\zlibstatic.lib" (if it doesn't exist) so MO finds it.
|
||||
|
||||
7z.dll (http://www.7-zip.org/download.html)
|
||||
- Part of the 7-zip program
|
||||
- Has to be the 32-bit dll! (approx. 893kb)
|
||||
- If you don't want to install 7-zip (32-bit) you can open the 7z installer (i.e. 7z920.exe) in an archiving tool and unpack only the 7z.dll
|
||||
|
||||
Recommended:
|
||||
------------
|
||||
|
||||
Qt Creator
|
||||
- Included in QtSDK but there might be a newer version as a separate download
|
||||
|
||||
Set up (using Qt Creator):
|
||||
--------------------------
|
||||
@@ -40,14 +42,15 @@ Set up (using Qt Creator):
|
||||
5. Switch the build configuration at the very top of the same page from "debug" to "release" (or vice versa) and repeat steps 3 and 4
|
||||
6. Compile the configuration(s) you want to use (debug and/or release) (Build All). This should compile correctly.
|
||||
7. return to the "projects" tab and switch to "Run Settings"
|
||||
8. Determine the folder of the qt binaries in the package you downloaded. This could be "QtSDK\Desktop\Qt\4.8.5\msvc2010\bin" or "Qt4.8.5\bin"
|
||||
For Release build:
|
||||
8r. Add a "Run configuration" that points to <your working copy>\output\ModOrganizer.exe
|
||||
9r. Copy "7z.dll" to <your working copy>\output\dlls
|
||||
10r. From QtSDK\Desktop\Qt\4.8.0\msvc2010\bin copy the following files to <your working copy>\output\dlls: QtCore4.dll, QtDeclarative4.dll, QtGui4.dll, QtNetwork4.dll, QtScript4.dll, QtSql4.dll, QtWebkit4.dll, QtXml4.dll, QtXmlPatterns4.dll
|
||||
9r. Add a "Run configuration" that points to <your working copy>\output\ModOrganizer.exe
|
||||
10r. Copy "7z.dll" to <your working copy>\output\dlls
|
||||
11r. From the qt binaries directory, copy the following files to <your working copy>\output\dlls: QtCore4.dll, QtDeclarative4.dll, QtGui4.dll, QtNetwork4.dll, QtScript4.dll, QtSql4.dll, QtWebkit4.dll, QtXml4.dll, QtXmlPatterns4.dll
|
||||
For Debug build:
|
||||
8d. Add a "Run configuration" that points to <your working copy>\outputd\ModOrganizer.exe
|
||||
9d. Copy "7z.dll" to <your working copy>\outputd\dlls
|
||||
10d. From QtSDK\Desktop\Qt\4.8.0\msvc2010\bin copy the following files to <your working copy>\outputd\dlls: QtCored4.dll, QtDeclaratived4.dll, QtGuid4.dll, QtNetworkd4.dll, QtScriptd4.dll, QtSqld4.dll, QtWebkitd4.dll, QtXmld4.dll, QtXmlPatternsd4.dll
|
||||
9d. Add a "Run configuration" that points to <your working copy>\outputd\ModOrganizer.exe
|
||||
10d. Copy "7z.dll" to <your working copy>\outputd\dlls
|
||||
11d. From the qt binaries copy the following files to <your working copy>\outputd\dlls: QtCored4.dll, QtDeclaratived4.dll, QtGuid4.dll, QtNetworkd4.dll, QtScriptd4.dll, QtSqld4.dll, QtWebkitd4.dll, QtXmld4.dll, QtXmlPatternsd4.dll
|
||||
|
||||
Now you should be able to compile and run Mod Organizer.
|
||||
Please note that when you change anything apart from the "organizer" subproject, qt creator may not pick up on the changes
|
||||
|
||||
+22
-4
@@ -153,7 +153,8 @@ QString DownloadManager::DownloadInfo::currentURL()
|
||||
|
||||
|
||||
DownloadManager::DownloadManager(NexusInterface *nexusInterface, QObject *parent)
|
||||
: IDownloadManager(parent), m_NexusInterface(nexusInterface), m_DirWatcher(), m_ShowHidden(false)
|
||||
: IDownloadManager(parent), m_NexusInterface(nexusInterface), m_DirWatcher(), m_ShowHidden(false),
|
||||
m_DateExpression("/Date\\((\\d+)\\)/")
|
||||
{
|
||||
connect(&m_DirWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
|
||||
}
|
||||
@@ -851,7 +852,6 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
setState(info, STATE_PAUSED);
|
||||
} else {
|
||||
if (bytesTotal > info->m_TotalSize) {
|
||||
qDebug("file size %s: %lld", qPrintable(info->m_FileName), bytesTotal);
|
||||
info->m_TotalSize = bytesTotal;
|
||||
}
|
||||
int oldProgress = info->m_Progress;
|
||||
@@ -883,6 +883,7 @@ void DownloadManager::createMetaFile(DownloadInfo *info)
|
||||
metaFile.setValue("name", info->m_NexusInfo.m_Name);
|
||||
metaFile.setValue("modName", info->m_NexusInfo.m_ModName);
|
||||
metaFile.setValue("version", info->m_NexusInfo.m_Version);
|
||||
metaFile.setValue("fileTime", info->m_NexusInfo.m_FileTime);
|
||||
metaFile.setValue("fileCategory", info->m_NexusInfo.m_FileCategory);
|
||||
metaFile.setValue("newestVersion", info->m_NexusInfo.m_NewestVersion);
|
||||
metaFile.setValue("category", info->m_NexusInfo.m_Category);
|
||||
@@ -914,11 +915,9 @@ void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant r
|
||||
|
||||
DownloadInfo *info = downloadInfoByID(userData.toInt());
|
||||
if (info == NULL) return;
|
||||
|
||||
info->m_NexusInfo.m_Category = result["category_id"].toInt();
|
||||
info->m_NexusInfo.m_ModName = result["name"].toString().trimmed();
|
||||
info->m_NexusInfo.m_NewestVersion = result["version"].toString();
|
||||
|
||||
if (info->m_FileID != 0) {
|
||||
setState(info, STATE_READY);
|
||||
} else {
|
||||
@@ -927,6 +926,17 @@ void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant r
|
||||
}
|
||||
|
||||
|
||||
QDateTime DownloadManager::matchDate(const QString &timeString)
|
||||
{
|
||||
if (m_DateExpression.exactMatch(timeString)) {
|
||||
return QDateTime::fromMSecsSinceEpoch(m_DateExpression.cap(1).toLongLong());
|
||||
} else {
|
||||
qWarning("date not matched: %s", qPrintable(timeString));
|
||||
return QDateTime::currentDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultData, int requestID)
|
||||
{
|
||||
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
|
||||
@@ -960,7 +970,11 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD
|
||||
(fileNameVariant == info->m_FileName) || (fileNameVariant == alternativeLocalName)) {
|
||||
info->m_NexusInfo.m_Name = fileInfo["name"].toString();
|
||||
info->m_NexusInfo.m_Version = fileInfo["version"].toString();
|
||||
if (info->m_NexusInfo.m_Version.isEmpty()) {
|
||||
info->m_NexusInfo.m_Version = info->m_NexusInfo.m_NewestVersion;
|
||||
}
|
||||
info->m_NexusInfo.m_FileCategory = fileInfo["category_id"].toInt();
|
||||
info->m_NexusInfo.m_FileTime = matchDate(fileInfo["date"].toString());
|
||||
info->m_FileID = fileInfo["id"].toInt();
|
||||
found = true;
|
||||
break;
|
||||
@@ -1014,7 +1028,11 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD
|
||||
|
||||
info.m_Name = result["name"].toString();
|
||||
info.m_Version = result["version"].toString();
|
||||
if (info.m_Version.isEmpty()) {
|
||||
info.m_Version = info.m_NewestVersion;
|
||||
}
|
||||
info.m_FileName = result["uri"].toString();
|
||||
info.m_FileTime = matchDate(result["date"].toString());
|
||||
|
||||
if (userData.isValid()) {
|
||||
m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(info), userData.toString()));
|
||||
|
||||
@@ -46,6 +46,7 @@ struct NexusInfo {
|
||||
QString m_NewestVersion;
|
||||
QString m_FileName;
|
||||
QVariantList m_DownloadMap;
|
||||
QDateTime m_FileTime;
|
||||
bool m_Set;
|
||||
};
|
||||
Q_DECLARE_METATYPE(NexusInfo)
|
||||
@@ -437,6 +438,8 @@ private:
|
||||
|
||||
DownloadInfo *downloadInfoByID(unsigned int id);
|
||||
|
||||
QDateTime matchDate(const QString &timeString);
|
||||
|
||||
private:
|
||||
|
||||
static const int AUTOMATIC_RETRIES = 3;
|
||||
@@ -458,6 +461,8 @@ private:
|
||||
|
||||
bool m_ShowHidden;
|
||||
|
||||
QRegExp m_DateExpression;
|
||||
|
||||
};
|
||||
|
||||
#endif // DOWNLOADMANAGER_H
|
||||
|
||||
+136
-51
@@ -144,8 +144,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
m_DirectoryStructure(new DirectoryEntry(L"data", NULL, 0)),
|
||||
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_DownloadManager(NexusInterface::instance(), this), m_InstallationManager(this),
|
||||
m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()),
|
||||
m_CurrentProfile(NULL), m_AskForNexusPW(false), m_LoginAttempted(false),
|
||||
m_ArchivesInit(false), m_ContextItem(NULL), m_ContextAction(NULL), m_CurrentSaveView(NULL),
|
||||
@@ -208,6 +207,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
}
|
||||
ui->espList->installEventFilter(&m_PluginList);
|
||||
|
||||
ui->bsaList->setLocalMoveOnly(true);
|
||||
|
||||
resizeLists(initSettings.contains("mod_list_state"), initSettings.contains("plugin_list_state"));
|
||||
|
||||
QMenu *linkMenu = new QMenu(this);
|
||||
@@ -975,7 +976,7 @@ void MainWindow::registerPluginTool(IPluginTool *tool)
|
||||
}
|
||||
|
||||
|
||||
bool MainWindow::registerPlugin(QObject *plugin)
|
||||
bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName)
|
||||
{
|
||||
{ // generic treatment for all plugins
|
||||
IPlugin *pluginObj = qobject_cast<IPlugin*>(plugin);
|
||||
@@ -983,6 +984,7 @@ bool MainWindow::registerPlugin(QObject *plugin)
|
||||
qDebug("not an IPlugin");
|
||||
return false;
|
||||
}
|
||||
plugin->setProperty("filename", fileName);
|
||||
m_Settings.registerPlugin(pluginObj);
|
||||
}
|
||||
|
||||
@@ -1017,7 +1019,7 @@ bool MainWindow::registerPlugin(QObject *plugin)
|
||||
try {
|
||||
QObject *proxiedPlugin = proxy->instantiate(pluginName);
|
||||
if (proxiedPlugin != NULL) {
|
||||
if (registerPlugin(proxiedPlugin)) {
|
||||
if (registerPlugin(proxiedPlugin, pluginName)) {
|
||||
qDebug("loaded plugin \"%s\"", QDir::toNativeSeparators(pluginName).toUtf8().constData());
|
||||
} else {
|
||||
qWarning("plugin \"%s\" failed to load", pluginName.toUtf8().constData());
|
||||
@@ -1052,7 +1054,7 @@ void MainWindow::loadPlugins()
|
||||
m_Settings.clearPlugins();
|
||||
|
||||
foreach (QObject *plugin, QPluginLoader::staticInstances()) {
|
||||
registerPlugin(plugin);
|
||||
registerPlugin(plugin, "");
|
||||
}
|
||||
|
||||
QFile loadCheck(QCoreApplication::applicationDirPath() + "/plugin_loadcheck.tmp");
|
||||
@@ -1095,7 +1097,7 @@ void MainWindow::loadPlugins()
|
||||
qCritical("failed to load plugin %s: %s",
|
||||
pluginName.toUtf8().constData(), pluginLoader.errorString().toUtf8().constData());
|
||||
} else {
|
||||
if (registerPlugin(pluginLoader.instance())) {
|
||||
if (registerPlugin(pluginLoader.instance(), pluginName)) {
|
||||
qDebug("loaded plugin \"%s\"", QDir::toNativeSeparators(pluginName).toUtf8().constData());
|
||||
} else {
|
||||
m_UnloadedPlugins.push_back(pluginName);
|
||||
@@ -1790,8 +1792,8 @@ void MainWindow::refreshBSAList()
|
||||
QTreeWidgetItem *newItem = new QTreeWidgetItem(strings);
|
||||
newItem->setData(0, Qt::UserRole, index);
|
||||
newItem->setData(1, Qt::UserRole, origin);
|
||||
// newItem->setFlags(newItem->flags() & ~Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable);
|
||||
newItem->setFlags(newItem->flags() | Qt::ItemIsUserCheckable);
|
||||
newItem->setFlags(newItem->flags() & ~Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable);
|
||||
// newItem->setFlags(newItem->flags() | Qt::ItemIsUserCheckable);
|
||||
newItem->setCheckState(0, (index != -1) ? Qt::Checked : Qt::Unchecked);
|
||||
if (m_Settings.forceEnableCoreFiles() && m_DefaultArchives.contains(filename)) {
|
||||
newItem->setCheckState(0, Qt::Checked);
|
||||
@@ -3166,7 +3168,6 @@ void MainWindow::testExtractBSA(int modIndex)
|
||||
|
||||
foreach (QFileInfo archiveInfo, archives) {
|
||||
BSA::Archive archive;
|
||||
|
||||
BSA::EErrorCode result = archive.read(archiveInfo.absoluteFilePath().toLocal8Bit().constData());
|
||||
if ((result != BSA::ERROR_NONE) && (result != BSA::ERROR_INVALIDHASHES)) {
|
||||
reportError(tr("failed to read %1: %2").arg(archiveInfo.fileName()).arg(result));
|
||||
@@ -3178,7 +3179,7 @@ void MainWindow::testExtractBSA(int modIndex)
|
||||
progress.setValue(0);
|
||||
progress.show();
|
||||
|
||||
archive.extractAll(modInfo->absolutePath().toUtf8().constData(),
|
||||
archive.extractAll(modInfo->absolutePath().toLocal8Bit().constData(),
|
||||
boost::bind(&MainWindow::extractProgress, this, boost::ref(progress), _1, _2));
|
||||
|
||||
if (result == BSA::ERROR_INVALIDHASHES) {
|
||||
@@ -3214,7 +3215,7 @@ void MainWindow::visitOnNexus_clicked()
|
||||
{
|
||||
int modID = m_ModList.data(m_ModList.index(m_ContextRow, 0), Qt::UserRole).toInt();
|
||||
if (modID > 0) {
|
||||
nexusLinkActivated(QString("%1/downloads/file.php?id=%2").arg(ToQString(GameInfo::instance().getNexusPage())).arg(modID));
|
||||
nexusLinkActivated(QString("%1/mods/%2").arg(ToQString(GameInfo::instance().getNexusPage())).arg(modID));
|
||||
} else {
|
||||
MessageDialog::showMessage(tr("Nexus ID for this Mod is unknown"), this);
|
||||
}
|
||||
@@ -3257,7 +3258,7 @@ void MainWindow::createModFromOverwrite()
|
||||
bool ok;
|
||||
name.update(QInputDialog::getText(this, tr("Create Mod..."),
|
||||
tr("This will move all files from overwrite into a new, regular mod.\n"
|
||||
"Please enter a name: "), QLineEdit::Normal, "", &ok),
|
||||
"Please enter a name:"), QLineEdit::Normal, "", &ok),
|
||||
GUESS_USER);
|
||||
if (!ok) {
|
||||
return;
|
||||
@@ -3309,7 +3310,7 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index)
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::addCategories(QMenu *menu, int targetID)
|
||||
bool MainWindow::populateMenuCategories(QMenu *menu, int targetID)
|
||||
{
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
|
||||
const std::set<int> &categories = modInfo->getCategories();
|
||||
@@ -3338,7 +3339,7 @@ bool MainWindow::addCategories(QMenu *menu, int targetID)
|
||||
targetMenu->addAction(checkableAction.take());
|
||||
|
||||
if (m_CategoryFactory.hasChildren(i)) {
|
||||
if (addCategories(targetMenu, m_CategoryFactory.getCategoryID(i)) || enabled) {
|
||||
if (populateMenuCategories(targetMenu, m_CategoryFactory.getCategoryID(i)) || enabled) {
|
||||
targetMenu->setIcon(QIcon(":/MO/gui/resources/check.png"));
|
||||
}
|
||||
}
|
||||
@@ -3347,12 +3348,12 @@ bool MainWindow::addCategories(QMenu *menu, int targetID)
|
||||
return childEnabled;
|
||||
}
|
||||
|
||||
void MainWindow::saveCategoriesFromMenu(QMenu *menu, int modRow)
|
||||
void MainWindow::replaceCategoriesFromMenu(QMenu *menu, int modRow)
|
||||
{
|
||||
ModInfo::Ptr modInfo = ModInfo::getByIndex(modRow);
|
||||
foreach (QAction* action, menu->actions()) {
|
||||
if (action->menu() != NULL) {
|
||||
saveCategoriesFromMenu(action->menu(), modRow);
|
||||
replaceCategoriesFromMenu(action->menu(), modRow);
|
||||
} else {
|
||||
QWidgetAction *widgetAction = qobject_cast<QWidgetAction*>(action);
|
||||
if (widgetAction != NULL) {
|
||||
@@ -3363,8 +3364,35 @@ void MainWindow::saveCategoriesFromMenu(QMenu *menu, int modRow)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::saveCategories()
|
||||
void MainWindow::addRemoveCategoriesFromMenu(QMenu *menu, int modRow)
|
||||
{
|
||||
if (m_ContextRow != -1 && m_ContextRow != modRow) {
|
||||
ModInfo::Ptr editedModInfo = ModInfo::getByIndex(m_ContextRow);
|
||||
foreach (QAction* action, menu->actions()) {
|
||||
if (action->menu() != NULL) {
|
||||
addRemoveCategoriesFromMenu(action->menu(), modRow);
|
||||
} else {
|
||||
QWidgetAction *widgetAction = qobject_cast<QWidgetAction*>(action);
|
||||
if (widgetAction != NULL) {
|
||||
QCheckBox *checkbox = qobject_cast<QCheckBox*>(widgetAction->defaultWidget());
|
||||
int categoryId = widgetAction->data().toInt();
|
||||
bool checkedBefore = editedModInfo->categorySet(categoryId);
|
||||
bool checkedAfter = checkbox->isChecked();
|
||||
|
||||
if (checkedBefore != checkedAfter) { // only update if the category was changed on the edited mod
|
||||
ModInfo::Ptr currentModInfo = ModInfo::getByIndex(modRow);
|
||||
currentModInfo->setCategory(categoryId, checkedAfter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//This block shouldn't be reached, but if it is then fall back to replace (context row is invalid or replacing edited mod)
|
||||
replaceCategoriesFromMenu(menu, modRow);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::addRemoveCategories_MenuHandler() {
|
||||
QMenu *menu = qobject_cast<QMenu*>(sender());
|
||||
if (menu == NULL) {
|
||||
qCritical("not a menu?");
|
||||
@@ -3383,11 +3411,16 @@ void MainWindow::saveCategories()
|
||||
selectedMods.append(temp.data().toString());
|
||||
if (temp.row() < min) min = temp.row();
|
||||
if (temp.row() > max) max = temp.row();
|
||||
saveCategoriesFromMenu(menu, mapToModel(&m_ModList, selected.at(i)).row());
|
||||
// save the currently selected mod for last... then we can use it as a pattern for what is changing...
|
||||
int modRow = m_ModListSortProxy->mapToSource(selected.at(i)).row();
|
||||
if (modRow != m_ContextRow) {
|
||||
addRemoveCategoriesFromMenu(menu,modRow);
|
||||
}
|
||||
}
|
||||
//m_ModList.notifyChange(min, max);
|
||||
//come back to the currently selected mod, after the others have been set
|
||||
replaceCategoriesFromMenu(menu, m_ContextRow);
|
||||
|
||||
m_ModList.notifyChange(-1);
|
||||
// refreshModList();
|
||||
|
||||
// find mods by their name because indices are invalidated
|
||||
QAbstractItemModel *model = ui->modList->model();
|
||||
@@ -3399,7 +3432,50 @@ void MainWindow::saveCategories()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
saveCategoriesFromMenu(menu, m_ContextRow);
|
||||
//For single mod selections, just do a replace
|
||||
replaceCategoriesFromMenu(menu, m_ContextRow);
|
||||
m_ModList.notifyChange(m_ContextRow);
|
||||
}
|
||||
|
||||
refreshFilters();
|
||||
}
|
||||
|
||||
void MainWindow::replaceCategories_MenuHandler() {
|
||||
QMenu *menu = qobject_cast<QMenu*>(sender());
|
||||
if (menu == NULL) {
|
||||
qCritical("not a menu?");
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndexList selected = ui->modList->selectionModel()->selectedRows();
|
||||
|
||||
if (selected.size() > 0) {
|
||||
int min = INT_MAX;
|
||||
int max = INT_MIN;
|
||||
|
||||
QStringList selectedMods;
|
||||
for (int i = 0; i < selected.size(); ++i) {
|
||||
QModelIndex temp = mapToModel(&m_ModList, selected.at(i));
|
||||
selectedMods.append(temp.data().toString());
|
||||
if (temp.row() < min) min = temp.row();
|
||||
if (temp.row() > max) max = temp.row();
|
||||
replaceCategoriesFromMenu(menu, mapToModel(&m_ModList, selected.at(i)).row());
|
||||
}
|
||||
|
||||
m_ModList.notifyChange(-1);
|
||||
|
||||
// find mods by their name because indices are invalidated
|
||||
QAbstractItemModel *model = ui->modList->model();
|
||||
Q_FOREACH(const QString &mod, selectedMods) {
|
||||
QModelIndexList matches = model->match(model->index(0, 0), Qt::DisplayRole, mod, 1,
|
||||
Qt::MatchFixedString | Qt::MatchCaseSensitive | Qt::MatchRecursive);
|
||||
if (matches.size() > 0) {
|
||||
ui->modList->selectionModel()->select(matches.at(0), QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//For single mod selections, just do a replace
|
||||
replaceCategoriesFromMenu(menu, m_ContextRow);
|
||||
m_ModList.notifyChange(m_ContextRow);
|
||||
}
|
||||
|
||||
@@ -3567,7 +3643,7 @@ void MainWindow::exportModListCSV()
|
||||
bool enabled = m_CurrentProfile->modEnabled(i);
|
||||
if ((selection.getChoiceData().toInt() == 1) && !enabled) {
|
||||
continue;
|
||||
} else if ((selection.getChoiceData().toInt() == 2) && !m_ModListSortProxy->filterMatches(info, enabled)) {
|
||||
} else if ((selection.getChoiceData().toInt() == 2) && !m_ModListSortProxy->filterMatchesMod(info, enabled)) {
|
||||
continue;
|
||||
}
|
||||
std::vector<ModInfo::EFlag> flags = info->getFlags();
|
||||
@@ -3633,11 +3709,15 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
|
||||
menu.addAction(tr("Restore Backup"), this, SLOT(restoreBackup_clicked()));
|
||||
menu.addAction(tr("Remove Backup..."), this, SLOT(removeMod_clicked()));
|
||||
} else {
|
||||
// Set categories is a separate menu connected to a push button. This way it doesn't simply close every time you hover the mouse outside
|
||||
QMenu *addCategoryMenu = new QMenu(tr("Set Category"));
|
||||
addCategories(addCategoryMenu, 0);
|
||||
connect(addCategoryMenu, SIGNAL(aboutToHide()), this, SLOT(saveCategories()));
|
||||
addMenuAsPushButton(&menu, addCategoryMenu);
|
||||
QMenu *addRemoveCategoriesMenu = new QMenu(tr("Add/Remove Categories"));
|
||||
populateMenuCategories(addRemoveCategoriesMenu, 0);
|
||||
connect(addRemoveCategoriesMenu, SIGNAL(aboutToHide()), this, SLOT(addRemoveCategories_MenuHandler()));
|
||||
addMenuAsPushButton(&menu, addRemoveCategoriesMenu);
|
||||
|
||||
QMenu *replaceCategoriesMenu = new QMenu(tr("Replace Categories"));
|
||||
populateMenuCategories(replaceCategoriesMenu, 0);
|
||||
connect(replaceCategoriesMenu, SIGNAL(aboutToHide()), this, SLOT(replaceCategories_MenuHandler()));
|
||||
addMenuAsPushButton(&menu, replaceCategoriesMenu);
|
||||
|
||||
QMenu *primaryCategoryMenu = new QMenu(tr("Primary Category"));
|
||||
connect(primaryCategoryMenu, SIGNAL(aboutToShow()), this, SLOT(addPrimaryCategoryCandidates()));
|
||||
@@ -3998,35 +4078,40 @@ void MainWindow::downloadRequested(QNetworkReply *reply, int modID, const QStrin
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::installTranslator(const QString &name)
|
||||
{
|
||||
QTranslator *translator = new QTranslator(this);
|
||||
QString fileName = name + "_" + m_CurrentLanguage;
|
||||
if (!translator->load(fileName, qApp->applicationDirPath() + "/translations")) {
|
||||
qWarning("localization file %s not found", qPrintable(fileName));
|
||||
}
|
||||
qApp->installTranslator(translator);
|
||||
m_Translators.push_back(translator);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::languageChange(const QString &newLanguage)
|
||||
{
|
||||
if (m_Translator != NULL) {
|
||||
QCoreApplication::removeTranslator(m_Translator);
|
||||
delete m_Translator;
|
||||
m_Translator = NULL;
|
||||
}
|
||||
if (m_TranslatorQt != NULL) {
|
||||
QCoreApplication::removeTranslator(m_TranslatorQt);
|
||||
delete m_TranslatorQt;
|
||||
m_TranslatorQt = NULL;
|
||||
foreach (QTranslator *trans, m_Translators) {
|
||||
qApp->removeTranslator(trans);
|
||||
}
|
||||
m_Translators.clear();
|
||||
|
||||
m_CurrentLanguage = newLanguage;
|
||||
|
||||
if (newLanguage != "en_US") {
|
||||
// add our own translations
|
||||
m_Translator = new QTranslator(this);
|
||||
QString locFile = ToQString(AppConfig::translationPrefix()) + "_" + newLanguage;
|
||||
if (!m_Translator->load(locFile, QCoreApplication::applicationDirPath() + "/translations")) {
|
||||
qDebug("localization %s not found", locFile.toUtf8().constData());
|
||||
installTranslator("qt");
|
||||
installTranslator(ToQString(AppConfig::translationPrefix()));
|
||||
foreach(IPlugin *plugin, m_Settings.plugins()) {
|
||||
QObject *pluginObj = dynamic_cast<QObject*>(plugin);
|
||||
if (pluginObj != NULL) {
|
||||
QVariant fileNameVariant = pluginObj->property("filename");
|
||||
if (fileNameVariant.isValid()) {
|
||||
QString fileName = QFileInfo(fileNameVariant.toString()).baseName();
|
||||
installTranslator(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
QCoreApplication::installTranslator(m_Translator);
|
||||
|
||||
// also add the translations for qt default strings
|
||||
m_TranslatorQt = new QTranslator(this);
|
||||
locFile = QString("qt_") + newLanguage;
|
||||
if (!m_TranslatorQt->load(locFile, QCoreApplication::applicationDirPath() + "/translations")) {
|
||||
qDebug("localization %s not found", locFile.toUtf8().constData());
|
||||
}
|
||||
QCoreApplication::installTranslator(m_TranslatorQt);
|
||||
}
|
||||
ui->retranslateUi(this);
|
||||
ui->profileBox->setItemText(0, QObject::tr("<Manage...>"));
|
||||
@@ -4659,7 +4744,7 @@ void MainWindow::extractBSATriggered()
|
||||
progress.setMaximum(100);
|
||||
progress.setValue(0);
|
||||
progress.show();
|
||||
archive.extractAll(QDir::toNativeSeparators(targetFolder).toUtf8().constData(),
|
||||
archive.extractAll(QDir::toNativeSeparators(targetFolder).toLocal8Bit().constData(),
|
||||
boost::bind(&MainWindow::extractProgress, this, boost::ref(progress), _1, _2));
|
||||
if (result == BSA::ERROR_INVALIDHASHES) {
|
||||
reportError(tr("This archive contains invalid hashes. Some files may be broken."));
|
||||
|
||||
+24
-7
@@ -197,7 +197,7 @@ private:
|
||||
void actionToToolButton(QAction *&sourceAction);
|
||||
bool verifyPlugin(MOBase::IPlugin *plugin);
|
||||
void registerPluginTool(MOBase::IPluginTool *tool);
|
||||
bool registerPlugin(QObject *pluginObj);
|
||||
bool registerPlugin(QObject *pluginObj, const QString &fileName);
|
||||
|
||||
void updateToolBar();
|
||||
void activateSelectedProfile();
|
||||
@@ -230,9 +230,23 @@ private:
|
||||
|
||||
void refreshFilters();
|
||||
|
||||
void saveCategoriesFromMenu(QMenu *menu, int modRow);
|
||||
/**
|
||||
* Sets category selections from menu; for multiple mods, this will only apply
|
||||
* the changes made in the menu (which is the delta between the current menu selection and the reference mod)
|
||||
* @param menu the menu after editing by the user
|
||||
* @param modRow index of the mod to edit
|
||||
*/
|
||||
void addRemoveCategoriesFromMenu(QMenu *menu, int modRow);
|
||||
|
||||
bool addCategories(QMenu *menu, int targetID);
|
||||
/**
|
||||
* Sets category selections from menu; for multiple mods, this will completely
|
||||
* replace the current set of categories on each selected with those selected in the menu
|
||||
* @param menu the menu after editing by the user
|
||||
* @param modRow index of the mod to edit
|
||||
*/
|
||||
void replaceCategoriesFromMenu(QMenu *menu, int modRow);
|
||||
|
||||
bool populateMenuCategories(QMenu *menu, int targetID);
|
||||
|
||||
void updateDownloadListDelegate();
|
||||
|
||||
@@ -272,6 +286,7 @@ private:
|
||||
|
||||
static void setupNetworkProxy(bool activate);
|
||||
void activateProxy(bool activate);
|
||||
void installTranslator(const QString &name);
|
||||
|
||||
private:
|
||||
|
||||
@@ -318,9 +333,6 @@ private:
|
||||
DownloadManager m_DownloadManager;
|
||||
InstallationManager m_InstallationManager;
|
||||
|
||||
QTranslator *m_Translator;
|
||||
QTranslator *m_TranslatorQt;
|
||||
|
||||
SelfUpdater m_Updater;
|
||||
|
||||
CategoryFactory &m_CategoryFactory;
|
||||
@@ -352,6 +364,9 @@ private:
|
||||
|
||||
SignalAboutToRunApplication m_AboutToRun;
|
||||
|
||||
QString m_CurrentLanguage;
|
||||
std::vector<QTranslator*> m_Translators;
|
||||
|
||||
private slots:
|
||||
|
||||
void showMessage(const QString &message);
|
||||
@@ -431,7 +446,9 @@ private slots:
|
||||
|
||||
void originModified(int originID);
|
||||
|
||||
void saveCategories();
|
||||
void addRemoveCategories_MenuHandler();
|
||||
void replaceCategories_MenuHandler();
|
||||
|
||||
void savePrimaryCategory();
|
||||
void addPrimaryCategoryCandidates();
|
||||
|
||||
|
||||
+5
-50
@@ -31,16 +31,7 @@
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -730,16 +721,7 @@ p, li { white-space: pre-wrap; }
|
||||
<string notr="true">Archives</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -819,16 +801,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
|
||||
<string>Data</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -898,16 +871,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
|
||||
<string>Saves</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -936,16 +900,7 @@ p, li { white-space: pre-wrap; }
|
||||
<string>Downloads</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
|
||||
@@ -541,6 +541,13 @@ bool ModInfoRegular::setName(const QString &name)
|
||||
void ModInfoRegular::setNotes(const QString ¬es)
|
||||
{
|
||||
m_Notes = notes;
|
||||
m_MetaInfoChanged = true;
|
||||
}
|
||||
|
||||
void ModInfoRegular::setNexusID(int modID)
|
||||
{
|
||||
m_NexusID = modID;
|
||||
m_MetaInfoChanged = true;
|
||||
}
|
||||
|
||||
void ModInfoRegular::setVersion(const VersionInfo &version)
|
||||
|
||||
+1
-1
@@ -570,7 +570,7 @@ public:
|
||||
*
|
||||
* @param modID the nexus mod id
|
||||
**/
|
||||
void setNexusID(int modID) { m_NexusID = modID; }
|
||||
void setNexusID(int modID);
|
||||
|
||||
/**
|
||||
* @brief set the version of this mod
|
||||
|
||||
+31
-15
@@ -209,7 +209,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>676</width>
|
||||
<width>668</width>
|
||||
<height>126</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -223,7 +223,16 @@
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -284,7 +293,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/resources/go-up.png</normaloff>:/MO/gui/resources/go-up.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
@@ -313,7 +322,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/resources/go-down.png</normaloff>:/MO/gui/resources/go-down.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
@@ -395,6 +404,9 @@ Most mods do not have optional esps, so chances are good you are looking at an e
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideLeft</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -405,13 +417,13 @@ Most mods do not have optional esps, so chances are good you are looking at an e
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>500</number>
|
||||
<number>365</number>
|
||||
</attribute>
|
||||
<attribute name="headerHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>300</number>
|
||||
<number>200</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
@@ -451,14 +463,17 @@ Most mods do not have optional esps, so chances are good you are looking at an e
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideLeft</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>500</number>
|
||||
<number>365</number>
|
||||
</attribute>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>300</number>
|
||||
<number>200</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
@@ -533,7 +548,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabNexus_2">
|
||||
<attribute name="icon">
|
||||
<iconset>
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/resources/internet-web-browser.png</normaloff>:/MO/gui/resources/internet-web-browser.png</iconset>
|
||||
</attribute>
|
||||
<attribute name="title">
|
||||
@@ -625,7 +640,7 @@ p, li { white-space: pre-wrap; }
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/refresh</normaloff>:/MO/gui/refresh</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
@@ -651,9 +666,8 @@ p, li { white-space: pre-wrap; }
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></string>
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;">
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
@@ -687,7 +701,7 @@ p, li { white-space: pre-wrap; }
|
||||
<string>Endorse</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/icon_favorite</normaloff>:/MO/gui/icon_favorite</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
@@ -782,6 +796,8 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -220,7 +220,7 @@ bool ModListSortProxy::hasConflictFlag(const std::vector<ModInfo::EFlag> &flags)
|
||||
}
|
||||
|
||||
|
||||
bool ModListSortProxy::filterMatches(ModInfo::Ptr info, bool enabled) const
|
||||
bool ModListSortProxy::filterMatchesMod(ModInfo::Ptr info, bool enabled) const
|
||||
{
|
||||
if (!m_CurrentFilter.isEmpty() &&
|
||||
!info->name().contains(m_CurrentFilter, Qt::CaseInsensitive)) {
|
||||
@@ -258,7 +258,7 @@ bool ModListSortProxy::filterMatches(ModInfo::Ptr info, bool enabled) const
|
||||
}
|
||||
|
||||
|
||||
bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex&) const
|
||||
bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||
{
|
||||
if (m_Profile == NULL) {
|
||||
return false;
|
||||
@@ -268,9 +268,25 @@ bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex&) const
|
||||
qWarning("invalid row idx %d", row);
|
||||
return false;
|
||||
}
|
||||
bool modEnabled = m_Profile->modEnabled(row);
|
||||
|
||||
return filterMatches(ModInfo::getByIndex(row), modEnabled);
|
||||
QModelIndex idx = sourceModel()->index(row, 0, parent);
|
||||
if (!idx.isValid()) {
|
||||
qDebug("invalid index");
|
||||
return false;
|
||||
}
|
||||
if (idx.isValid() && sourceModel()->hasChildren(idx)) {
|
||||
for (int i = 0; i < sourceModel()->rowCount(idx); ++i) {
|
||||
if (filterAcceptsRow(i, idx)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
bool modEnabled = idx.sibling(row, 0).data(Qt::CheckStateRole).toInt() == Qt::Checked;
|
||||
unsigned int index = idx.data(Qt::UserRole + 1).toInt();
|
||||
return filterMatchesMod(ModInfo::getByIndex(index), modEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -52,14 +52,7 @@ public:
|
||||
**/
|
||||
void disableAllVisible();
|
||||
|
||||
bool filterMatches(ModInfo::Ptr info, bool enabled) const;
|
||||
|
||||
/*
|
||||
virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const {
|
||||
int rc = QSortFilterProxyModel::rowCount(parent);
|
||||
qDebug() << parent << " - " << rc;
|
||||
return rc;
|
||||
}*/
|
||||
bool filterMatchesMod(ModInfo::Ptr info, bool enabled) const;
|
||||
|
||||
virtual bool hasChildren ( const QModelIndex & parent = QModelIndex() ) const {
|
||||
return rowCount(parent) > 0;
|
||||
|
||||
+35
-24
@@ -380,29 +380,33 @@ void NexusInterface::nextRequest()
|
||||
info.m_Timeout->setInterval(60000);
|
||||
|
||||
QString url;
|
||||
switch (info.m_Type) {
|
||||
case NXMRequestInfo::TYPE_DESCRIPTION: {
|
||||
url = QString("%1/Mods/%2/").arg(info.m_URL).arg(info.m_ModID);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_FILES: {
|
||||
url = QString("%1/Files/indexfrommod/%2/").arg(info.m_URL).arg(info.m_ModID);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_FILEINFO: {
|
||||
url = QString("%1/Files/%2/").arg(info.m_URL).arg(info.m_FileID);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_DOWNLOADURL: {
|
||||
url = QString("%1/Files/download/%2").arg(info.m_URL).arg(info.m_FileID);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: {
|
||||
url = QString("%1/Mods/toggleendorsement/%2?lvote=%3").arg(info.m_URL).arg(info.m_ModID).arg(!info.m_Endorse);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_GETUPDATES: {
|
||||
QString modIDList = VectorJoin<int>(info.m_ModIDList, ",");
|
||||
modIDList = "[" + modIDList + "]";
|
||||
url = QString("%1/Mods/GetUpdates?ModList=%2").arg(info.m_URL).arg(modIDList);
|
||||
} break;
|
||||
if (!info.m_Reroute) {
|
||||
switch (info.m_Type) {
|
||||
case NXMRequestInfo::TYPE_DESCRIPTION: {
|
||||
url = QString("%1/Mods/%2/").arg(info.m_URL).arg(info.m_ModID);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_FILES: {
|
||||
url = QString("%1/Files/indexfrommod/%2/").arg(info.m_URL).arg(info.m_ModID);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_FILEINFO: {
|
||||
url = QString("%1/Files/%2/").arg(info.m_URL).arg(info.m_FileID);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_DOWNLOADURL: {
|
||||
url = QString("%1/Files/download/%2").arg(info.m_URL).arg(info.m_FileID);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_TOGGLEENDORSEMENT: {
|
||||
url = QString("%1/Mods/toggleendorsement/%2?lvote=%3").arg(info.m_URL).arg(info.m_ModID).arg(!info.m_Endorse);
|
||||
} break;
|
||||
case NXMRequestInfo::TYPE_GETUPDATES: {
|
||||
QString modIDList = VectorJoin<int>(info.m_ModIDList, ",");
|
||||
modIDList = "[" + modIDList + "]";
|
||||
url = QString("%1/Mods/GetUpdates?ModList=%2").arg(info.m_URL).arg(modIDList);
|
||||
} break;
|
||||
}
|
||||
url.append(QString("?game_id=%1").arg(GameInfo::instance().getNexusGameID()));
|
||||
} else {
|
||||
url = info.m_URL;
|
||||
}
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/xml");
|
||||
request.setRawHeader("User-Agent",
|
||||
@@ -433,13 +437,21 @@ void NexusInterface::requestFinished(std::list<NXMRequestInfo>::iterator iter)
|
||||
qWarning("request failed: %s", reply->errorString().toUtf8().constData());
|
||||
emit nxmRequestFailed(iter->m_ModID, iter->m_UserData, iter->m_ID, reply->errorString());
|
||||
} else {
|
||||
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (statusCode == 301) {
|
||||
// redirect request, return request to queue
|
||||
iter->m_URL = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
|
||||
iter->m_Reroute = true;
|
||||
m_RequestQueue.enqueue(*iter);
|
||||
nextRequest();
|
||||
return;
|
||||
}
|
||||
QByteArray data = reply->readAll();
|
||||
if (data.isNull() || data.isEmpty() || (strcmp(data.constData(), "null") == 0)) {
|
||||
QString nexusError(reply->rawHeader("NexusErrorInfo"));
|
||||
if (nexusError.length() == 0) {
|
||||
nexusError = tr("empty response");
|
||||
}
|
||||
|
||||
emit nxmRequestFailed(iter->m_ModID, iter->m_UserData, iter->m_ID, nexusError);
|
||||
} else {
|
||||
bool ok;
|
||||
@@ -509,7 +521,6 @@ void NexusInterface::requestTimeout()
|
||||
qWarning("invalid sender type");
|
||||
return;
|
||||
}
|
||||
qWarning("request timeout");
|
||||
for (std::list<NXMRequestInfo>::iterator iter = m_ActiveRequest.begin(); iter != m_ActiveRequest.end(); ++iter) {
|
||||
if (iter->m_Timeout == timer) {
|
||||
// this abort causes a "request failed" which cleans up the rest
|
||||
|
||||
@@ -270,18 +270,19 @@ private:
|
||||
QVariant m_UserData;
|
||||
QTimer *m_Timeout;
|
||||
QString m_URL;
|
||||
bool m_Reroute;
|
||||
int m_ID;
|
||||
int m_Endorse;
|
||||
|
||||
NXMRequestInfo(int modID, Type type, QVariant userData, const QString &url)
|
||||
: m_ModID(modID), m_FileID(0), m_Reply(NULL), m_Type(type), m_UserData(userData),
|
||||
m_Timeout(NULL), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
|
||||
m_Timeout(NULL), m_Reroute(false), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
|
||||
NXMRequestInfo(std::vector<int> modIDList, Type type, QVariant userData, const QString &url)
|
||||
: m_ModID(-1), m_ModIDList(modIDList), m_FileID(0), m_Reply(NULL), m_Type(type), m_UserData(userData),
|
||||
m_Timeout(NULL), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
|
||||
m_Timeout(NULL), m_Reroute(false), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
|
||||
NXMRequestInfo(int modID, int fileID, Type type, QVariant userData, const QString &url)
|
||||
: m_ModID(modID), m_FileID(fileID), m_Reply(NULL), m_Type(type), m_UserData(userData),
|
||||
m_Timeout(NULL), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
|
||||
m_Timeout(NULL), m_Reroute(false), m_ID(s_NextID.fetchAndAddAcquire(1)), m_URL(url) {}
|
||||
|
||||
private:
|
||||
static QAtomicInt s_NextID;
|
||||
|
||||
+3
-4
@@ -207,13 +207,12 @@ CONFIG += embed_manifest_exe
|
||||
# QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'highestAvailable\' uiAccess=\'false\'\"
|
||||
|
||||
TRANSLATIONS = organizer_de.ts \
|
||||
organizer_es.ts \
|
||||
organizer_fr.ts \
|
||||
organizer_zh_TW.ts \
|
||||
organizer_es.ts \
|
||||
organizer_fr.ts \
|
||||
organizer_zh_TW.ts \
|
||||
organizer_zh_CN.ts \
|
||||
organizer_cs.ts \
|
||||
organizer_tr.ts \
|
||||
organizer_en.ts \
|
||||
organizer_ru.ts
|
||||
|
||||
!isEmpty(TRANSLATIONS) {
|
||||
|
||||
+201
-206
File diff suppressed because it is too large
Load Diff
+201
-206
File diff suppressed because it is too large
Load Diff
+201
-206
File diff suppressed because it is too large
Load Diff
+201
-206
File diff suppressed because it is too large
Load Diff
+201
-206
File diff suppressed because it is too large
Load Diff
+201
-206
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user