mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2b799bd6b | ||
|
|
185eb8e5ef | ||
|
|
63efd21a6a | ||
|
|
ed67ac2113 | ||
|
|
9a33dc1480 | ||
|
|
1b0c437788 | ||
|
|
5e530becc2 | ||
|
|
d9835cc4ae | ||
|
|
18ea79c2d0 | ||
|
|
37a6989ba8 | ||
|
|
830b63c4e2 | ||
|
|
662772c2fc | ||
|
|
027edcf688 | ||
|
|
ff51aa10c2 | ||
|
|
cbc9d00584 | ||
|
|
e15f768a15 | ||
|
|
e63eba2ca1 | ||
|
|
20008e17b7 | ||
|
|
c24200bc04 | ||
|
|
25a9290cd5 | ||
|
|
efe657c23e | ||
|
|
571347d2de | ||
|
|
346bc630f8 | ||
|
|
013890f644 | ||
|
|
3559364473 | ||
|
|
92cdf41243 | ||
|
|
789e95ca58 | ||
|
|
9b9a1f435e | ||
|
|
7f82ffa664 | ||
|
|
68a1afed49 | ||
|
|
7b1ece5f28 | ||
|
|
2306e006dc | ||
|
|
f6cd53e932 | ||
|
|
5335188e63 | ||
|
|
dac716bb86 | ||
|
|
c486220d20 | ||
|
|
0af33ccddf | ||
|
|
413c045383 | ||
|
|
1266e13921 | ||
|
|
f4af3264f0 | ||
|
|
f61236e4cf | ||
|
|
d7e6fd1dd6 | ||
|
|
9d9dbd9f7e | ||
|
|
93763a9364 | ||
|
|
a94977988b | ||
|
|
c501b5cca0 | ||
|
|
c87d97de8c | ||
|
|
4914fd172d | ||
|
|
02fe0d3384 | ||
|
|
e76891b926 | ||
|
|
b53be165fd | ||
|
|
849d00521a | ||
|
|
deb3c5ca21 | ||
|
|
25448ef076 | ||
|
|
40919c1520 | ||
|
|
79c451bb17 | ||
|
|
87292ca30f | ||
|
|
c0b55690bc | ||
|
|
f1384cdfa7 | ||
|
|
c9658e1a65 | ||
|
|
9431597e66 | ||
|
|
4566b51093 | ||
|
|
2212ad6f1c | ||
|
|
6142872620 | ||
|
|
4cae1397e7 | ||
|
|
7fbfc12118 | ||
|
|
4eaa0d16bb | ||
|
|
a219d03444 | ||
|
|
ad01e1d608 | ||
|
|
aaa1523db9 | ||
|
|
effd05df06 | ||
|
|
545b7b4eb7 | ||
|
|
71830a65d4 | ||
|
|
bde2e5fca1 | ||
|
|
15bbfdfa6f | ||
|
|
a85a6e635e | ||
|
|
9abb3ca162 | ||
|
|
5588b8b756 | ||
|
|
d48392c89f | ||
|
|
21d61e617b | ||
|
|
a48a20f13f | ||
|
|
2e09e633bd | ||
|
|
1189b8cc33 | ||
|
|
17f1cf0aab | ||
|
|
78cd0110d3 | ||
|
|
2c57899cf6 | ||
|
|
3dbfba91e1 | ||
|
|
2c53f9d934 | ||
|
|
6323a348da | ||
|
|
73842ee245 | ||
|
|
122744454c | ||
|
|
5de173ba1a | ||
|
|
eb26120332 | ||
|
|
6056202ead | ||
|
|
c1d90b131b | ||
|
|
63a66c8754 | ||
|
|
ab95f78689 | ||
|
|
9e66799abf | ||
|
|
dce6507dad | ||
|
|
42d2344f0b | ||
|
|
18e49b71b5 | ||
|
|
fcb29afe83 | ||
|
|
cf52aa335a | ||
|
|
9c35443780 | ||
|
|
9c6c01df56 | ||
|
|
b83807e4d5 | ||
|
|
2d50b17243 | ||
|
|
5a1d4e8783 | ||
|
|
478aeeb28c | ||
|
|
07fc9d3546 | ||
|
|
15ab8d5c5e | ||
|
|
192f14b001 | ||
|
|
3ccceb19e1 | ||
|
|
2d9a2a0432 | ||
|
|
ac650ae078 | ||
|
|
1a91174757 | ||
|
|
e2ec6632ec | ||
|
|
b1a3bdd6e8 | ||
|
|
22a004be2e | ||
|
|
a3cb400152 | ||
|
|
3e29d31231 | ||
|
|
edf48bca6f | ||
|
|
33e11e2056 | ||
|
|
67fb7e56d3 | ||
|
|
979206228d | ||
|
|
ba162804cd | ||
|
|
c6751b690a | ||
|
|
138154aca0 | ||
|
|
c576f1ff40 | ||
|
|
c4636d891f | ||
|
|
8ea8444dc8 | ||
|
|
2232bdfc77 | ||
|
|
258bddb6b7 | ||
|
|
364289db72 | ||
|
|
ef771fd8ca | ||
|
|
2060df1585 | ||
|
|
9a973ccf5f | ||
|
|
a2eb3e0266 | ||
|
|
d65031c814 | ||
|
|
c27e718fbd | ||
|
|
43b2df9077 | ||
|
|
79b2e52a58 | ||
|
|
16a7ef78d3 | ||
|
|
74202cc743 | ||
|
|
8f86130759 | ||
|
|
17e4ec7b13 | ||
|
|
9a426a2474 | ||
|
|
80594d6e1a | ||
|
|
56473e0ec8 | ||
|
|
71988e386c | ||
|
|
5e7c0fddf0 | ||
|
|
b0c15c9cfb | ||
|
|
f92027bea6 | ||
|
|
a31b5495b8 | ||
|
|
fc19486f53 | ||
|
|
232bbfb23b | ||
|
|
2af99f2170 | ||
|
|
796224d733 | ||
|
|
1e4b5d2436 | ||
|
|
94ef8dffbc | ||
|
|
7b1821a518 | ||
|
|
fb0d4d5e5a |
@@ -0,0 +1,16 @@
|
||||
root = true
|
||||
|
||||
[*.cpp]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
|
||||
[*.h]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
|
||||
[*.ui]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
@@ -20,7 +20,7 @@ Through the work of a few people of the community MO2 has come quite far, now it
|
||||
## Reporting Issues:
|
||||
Issues should be reported to the GitHub page or on the open discord server: [ModOrganizerDevs](https://discord.gg/vD2ZbfX). Here is also where dev builds are tested, bugs are reported and investigated, suggestions are discussed and a lot more.
|
||||
|
||||
Credits to Tannin, LePresidente, Silarn, erasmux, AL12 and many others for the development.
|
||||
Credits to Tannin, LePresidente, Silarn, erasmux, AL12, LostDragonist, AnyOldName3 and many others for the development.
|
||||
|
||||
## Download Location
|
||||
|
||||
@@ -49,6 +49,7 @@ Here is a complete list:
|
||||
* https://github.com/Modorganizer2/modorganizer-check_fnis
|
||||
* https://github.com/Modorganizer2/modorganizer-diagnose_basic
|
||||
* https://github.com/Modorganizer2/modorganizer-esptk
|
||||
* https://github.com/ModOrganizer2/modorganizer-fnistool
|
||||
* https://github.com/Modorganizer2/modorganizer-helper
|
||||
* https://github.com/Modorganizer2/modorganizer-game_fallout3
|
||||
* https://github.com/Modorganizer2/modorganizer-game_fallout4
|
||||
@@ -60,6 +61,7 @@ Here is a complete list:
|
||||
* https://github.com/Modorganizer2/modorganizer-game_oblivion
|
||||
* https://github.com/Modorganizer2/modorganizer-game_skyrim
|
||||
* https://github.com/Modorganizer2/modorganizer-game_skyrimSE
|
||||
* https://github.com/ModOrganizer2/modorganizer-game_skyrimVR
|
||||
* https://github.com/Modorganizer2/modorganizer-game_ttw
|
||||
* https://github.com/Modorganizer2/modorganizer-installer_bain
|
||||
* https://github.com/Modorganizer2/modorganizer-installer_bundle
|
||||
|
||||
+7
-1
@@ -37,6 +37,7 @@ SET(organizer_SRCS
|
||||
modinfoforeign.cpp
|
||||
modinfooverwrite.cpp
|
||||
modinforegular.cpp
|
||||
modinfoseparator.cpp
|
||||
modinfowithconflictinfo.cpp
|
||||
messagedialog.cpp
|
||||
mainwindow.cpp
|
||||
@@ -90,6 +91,7 @@ SET(organizer_SRCS
|
||||
usvfsconnector.cpp
|
||||
eventfilter.cpp
|
||||
moshortcut.cpp
|
||||
listdialog.cpp
|
||||
|
||||
shared/windows_error.cpp
|
||||
shared/error_report.cpp
|
||||
@@ -128,6 +130,7 @@ SET(organizer_HDRS
|
||||
modinfoforeign.h
|
||||
modinfooverwrite.h
|
||||
modinforegular.h
|
||||
modinfoseparator.h
|
||||
modinfowithconflictinfo.h
|
||||
messagedialog.h
|
||||
mainwindow.h
|
||||
@@ -183,6 +186,7 @@ SET(organizer_HDRS
|
||||
eventfilter.h
|
||||
descriptionpage.h
|
||||
moshortcut.h
|
||||
listdialog.h
|
||||
|
||||
shared/windows_error.h
|
||||
shared/error_report.h
|
||||
@@ -223,6 +227,7 @@ SET(organizer_UIS
|
||||
previewdialog.ui
|
||||
browserdialog.ui
|
||||
aboutdialog.ui
|
||||
listdialog.ui
|
||||
)
|
||||
|
||||
SET(organizer_QRCS
|
||||
@@ -288,7 +293,8 @@ INCLUDE_DIRECTORIES(${project_path}/uibase/src
|
||||
${project_path}/esptk/src
|
||||
${project_path}/archive/src
|
||||
${project_path}/../usvfs/include
|
||||
${project_path}/game_gamebryo/src
|
||||
${project_path}/game_gamebryo/src/gamebryo
|
||||
${project_path}/game_gamebryo/src/creation
|
||||
${project_path}/game_features/src
|
||||
${project_path}/githubpp/src
|
||||
${LZ4_ROOT}/include)
|
||||
|
||||
+6
-1
@@ -189,6 +189,11 @@
|
||||
<property name="text">
|
||||
<string notr="true">Silarn</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">LostDragonist</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -208,7 +213,7 @@
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">AnyOldName3 (Python Plugins)</string>
|
||||
<string notr="true">AnyOldName3</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
|
||||
+4
-2
@@ -47,8 +47,10 @@ public:
|
||||
static const int CATEGORY_SPECIAL_NOCATEGORY = 10003;
|
||||
static const int CATEGORY_SPECIAL_CONFLICT = 10004;
|
||||
static const int CATEGORY_SPECIAL_NOTENDORSED = 10005;
|
||||
static const int CATEGORY_SPECIAL_MANAGED = 10006;
|
||||
static const int CATEGORY_SPECIAL_UNMANAGED = 10007;
|
||||
static const int CATEGORY_SPECIAL_BACKUP = 10006;
|
||||
static const int CATEGORY_SPECIAL_MANAGED = 10007;
|
||||
static const int CATEGORY_SPECIAL_UNMANAGED = 10008;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -272,6 +272,11 @@ void DownloadListWidgetDelegate::issueVisitOnNexus()
|
||||
emit visitOnNexus(m_ContextRow);
|
||||
}
|
||||
|
||||
void DownloadListWidgetDelegate::issueOpenFile()
|
||||
{
|
||||
emit openFile(m_ContextRow);
|
||||
}
|
||||
|
||||
void DownloadListWidgetDelegate::issueOpenInDownloadsFolder()
|
||||
{
|
||||
emit openInDownloadsFolder(m_ContextRow);
|
||||
@@ -375,6 +380,7 @@ bool DownloadListWidgetDelegate::editorEvent(QEvent *event, QAbstractItemModel *
|
||||
menu.addAction(tr("Visit on Nexus"), this,SLOT(issueVisitOnNexus()));
|
||||
}
|
||||
|
||||
menu.addAction(tr("Open File"), this, SLOT(issueOpenFile()));
|
||||
menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder()));
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
@@ -72,6 +72,7 @@ signals:
|
||||
void pauseDownload(int index);
|
||||
void resumeDownload(int index);
|
||||
void visitOnNexus(int index);
|
||||
void openFile(int index);
|
||||
void openInDownloadsFolder(int index);
|
||||
|
||||
protected:
|
||||
@@ -93,6 +94,7 @@ private slots:
|
||||
void issueRestoreToView();
|
||||
void issueRestoreToViewAll();
|
||||
void issueVisitOnNexus();
|
||||
void issueOpenFile();
|
||||
void issueOpenInDownloadsFolder();
|
||||
void issueCancel();
|
||||
void issuePause();
|
||||
|
||||
@@ -247,6 +247,11 @@ void DownloadListWidgetCompactDelegate::issueVisitOnNexus()
|
||||
emit visitOnNexus(m_ContextIndex.row());
|
||||
}
|
||||
|
||||
void DownloadListWidgetCompactDelegate::issueOpenFile()
|
||||
{
|
||||
emit openFile(m_ContextIndex.row());
|
||||
}
|
||||
|
||||
void DownloadListWidgetCompactDelegate::issueOpenInDownloadsFolder()
|
||||
{
|
||||
emit openInDownloadsFolder(m_ContextIndex.row());
|
||||
@@ -361,6 +366,7 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem
|
||||
}else {
|
||||
menu.addAction(tr("Visit on Nexus"), this, SLOT(issueVisitOnNexus()));
|
||||
}
|
||||
menu.addAction(tr("Open File"), this, SLOT(issueOpenFile()));
|
||||
menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder()));
|
||||
menu.addSeparator();
|
||||
menu.addAction(tr("Delete"), this, SLOT(issueDelete()));
|
||||
|
||||
@@ -70,6 +70,7 @@ signals:
|
||||
void pauseDownload(int index);
|
||||
void resumeDownload(int index);
|
||||
void visitOnNexus(int index);
|
||||
void openFile(int index);
|
||||
void openInDownloadsFolder(int index);
|
||||
|
||||
protected:
|
||||
@@ -92,6 +93,7 @@ private slots:
|
||||
void issueRestoreToView();
|
||||
void issueRestoreToViewAll();
|
||||
void issueVisitOnNexus();
|
||||
void issueOpenFile();
|
||||
void issueOpenInDownloadsFolder();
|
||||
void issueCancel();
|
||||
void issuePause();
|
||||
|
||||
+41
-22
@@ -703,7 +703,7 @@ void DownloadManager::removeDownload(int index, bool deleteFile)
|
||||
DownloadState minState;
|
||||
if (index == -3) {
|
||||
minState = STATE_UNINSTALLED;
|
||||
}
|
||||
}
|
||||
else
|
||||
minState = index == -1 ? STATE_READY : STATE_INSTALLED;
|
||||
|
||||
@@ -804,8 +804,10 @@ void DownloadManager::resumeDownloadInt(int index)
|
||||
if (info->isPausedState() || info->m_State == STATE_PAUSING) {
|
||||
if (info->m_State == STATE_PAUSING) {
|
||||
if (info->m_Output.isOpen()) {
|
||||
info->m_Output.write(info->m_Reply->readAll());
|
||||
setState(info, STATE_PAUSED);
|
||||
writeData(info);
|
||||
if (info->m_State == STATE_PAUSING) {
|
||||
setState(info, STATE_PAUSED);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((info->m_Urls.size() == 0)
|
||||
@@ -927,10 +929,27 @@ void DownloadManager::visitOnNexus(int index)
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadManager::openFile(int index)
|
||||
{
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
reportError(tr("OpenFile: invalid download index %1").arg(index));
|
||||
return;
|
||||
}
|
||||
QDir path = QDir(m_OutputDirectory);
|
||||
if (path.exists(getFileName(index))) {
|
||||
|
||||
::ShellExecuteW(nullptr, L"open", ToWString(QDir::toNativeSeparators(getFilePath(index))).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
::ShellExecuteW(nullptr, L"explore", ToWString(QDir::toNativeSeparators(m_OutputDirectory)).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
void DownloadManager::openInDownloadsFolder(int index)
|
||||
{
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
reportError(tr("VisitNexus: invalid download index %1").arg(index));
|
||||
reportError(tr("OpenFileInDownloadsFolder: invalid download index %1").arg(index));
|
||||
return;
|
||||
}
|
||||
QString params = "/select,\"";
|
||||
@@ -1345,10 +1364,7 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
void DownloadManager::downloadReadyRead()
|
||||
{
|
||||
try {
|
||||
DownloadInfo *info = findDownload(this->sender());
|
||||
if (info != nullptr) {
|
||||
info->m_Output.write(info->m_Reply->readAll());
|
||||
}
|
||||
writeData(findDownload(this->sender()));
|
||||
} catch (const std::bad_alloc&) {
|
||||
reportError(tr("Memory allocation error (in processing downloaded data)."));
|
||||
}
|
||||
@@ -1428,18 +1444,6 @@ QDateTime DownloadManager::matchDate(const QString &timeString)
|
||||
}
|
||||
|
||||
|
||||
static EFileCategory convertFileCategory(int id)
|
||||
{
|
||||
// TODO: need to handle file categories in the mod page plugin
|
||||
switch (id) {
|
||||
case 0: return TYPE_MAIN;
|
||||
case 1: return TYPE_UPDATE;
|
||||
case 2: return TYPE_OPTION;
|
||||
default: return TYPE_MAIN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DownloadManager::nxmFilesAvailable(QString, int, QVariant userData, QVariant resultData, int requestID)
|
||||
{
|
||||
std::set<int>::iterator idIter = m_RequestIDs.find(requestID);
|
||||
@@ -1476,7 +1480,7 @@ void DownloadManager::nxmFilesAvailable(QString, int, QVariant userData, QVarian
|
||||
if (!info->m_FileInfo->version.isValid()) {
|
||||
info->m_FileInfo->version = info->m_FileInfo->newestVersion;
|
||||
}
|
||||
info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt());
|
||||
info->m_FileInfo->fileCategory = fileInfo["category_id"].toInt();
|
||||
info->m_FileInfo->fileTime = matchDate(fileInfo["date"].toString());
|
||||
info->m_FileInfo->fileID = fileInfo["id"].toInt();
|
||||
info->m_FileInfo->fileName = fileInfo["uri"].toString();
|
||||
@@ -1501,7 +1505,7 @@ void DownloadManager::nxmFilesAvailable(QString, int, QVariant userData, QVarian
|
||||
QVariantMap fileInfo = selection.getChoiceData().toMap();
|
||||
info->m_FileInfo->name = fileInfo["name"].toString();
|
||||
info->m_FileInfo->version.parse(fileInfo["version"].toString());
|
||||
info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt());
|
||||
info->m_FileInfo->fileCategory = fileInfo["category_id"].toInt();
|
||||
info->m_FileInfo->fileID = fileInfo["id"].toInt();
|
||||
} else {
|
||||
emit showMessage(tr("No matching file found on Nexus! Maybe this file is no longer available or it was renamed?"));
|
||||
@@ -1835,3 +1839,18 @@ void DownloadManager::checkDownloadTimeout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadManager::writeData(DownloadInfo *info)
|
||||
{
|
||||
if (info != nullptr) {
|
||||
qint64 ret = info->m_Output.write(info->m_Reply->readAll());
|
||||
if (ret < info->m_Reply->size()) {
|
||||
QString fileName = info->m_FileName; // m_FileName may be destroyed after setState
|
||||
setState(info, DownloadState::STATE_CANCELED);
|
||||
qCritical(QString("Unable to write download \"%2\" to drive (return %1)").arg(ret).arg(info->m_FileName).toLocal8Bit());
|
||||
reportError(tr("Unable to write download to drive (return %1).\n"
|
||||
"Check the drive's available storage.\n\n"
|
||||
"Canceling download \"%2\"...").arg(ret).arg(fileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -445,6 +445,8 @@ public slots:
|
||||
|
||||
void visitOnNexus(int index);
|
||||
|
||||
void openFile(int index);
|
||||
|
||||
void openInDownloadsFolder(int index);
|
||||
|
||||
void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID);
|
||||
@@ -522,6 +524,8 @@ private:
|
||||
|
||||
static QString getFileTypeString(int fileType);
|
||||
|
||||
void writeData(DownloadInfo *info);
|
||||
|
||||
private:
|
||||
|
||||
static const int AUTOMATIC_RETRIES = 3;
|
||||
|
||||
+928
-917
File diff suppressed because it is too large
Load Diff
+227
-224
@@ -1,224 +1,227 @@
|
||||
/*
|
||||
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 INSTALLATIONMANAGER_H
|
||||
#define INSTALLATIONMANAGER_H
|
||||
|
||||
|
||||
#include <iinstallationmanager.h>
|
||||
#include <iplugininstaller.h>
|
||||
#include <guessedvalue.h>
|
||||
|
||||
#include <QObject>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <archive.h>
|
||||
#include <QProgressDialog>
|
||||
#include <set>
|
||||
#include <errorcodes.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief manages the installation of mod archives
|
||||
* This currently supports two special kind of archives:
|
||||
* - "simple" archives: properly packaged archives without options, so they can be extracted to the (virtual) data directory directly
|
||||
* - "complex" bain archives: archives with options for the bain system.
|
||||
* All other archives are managed through the manual "InstallDialog"
|
||||
* @todo this may be a good place to support plugins
|
||||
**/
|
||||
class InstallationManager : public QObject, public MOBase::IInstallationManager
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
*
|
||||
* @param parent parent object.
|
||||
**/
|
||||
explicit InstallationManager();
|
||||
|
||||
virtual ~InstallationManager();
|
||||
|
||||
void setParentWidget(QWidget *widget);
|
||||
|
||||
void setURL(const QString &url);
|
||||
|
||||
/**
|
||||
* @brief update the directory where mods are to be installed
|
||||
* @param modsDirectory the mod directory
|
||||
* @note this is called a lot, probably redundantly
|
||||
*/
|
||||
void setModsDirectory(const QString &modsDirectory) { m_ModsDirectory = modsDirectory; }
|
||||
|
||||
/**
|
||||
* @brief update the directory where downloads are stored
|
||||
* @param downloadDirectory the download directory
|
||||
*/
|
||||
void setDownloadDirectory(const QString &downloadDirectory) { m_DownloadsDirectory = downloadDirectory; }
|
||||
|
||||
/**
|
||||
* @brief install a mod from an archive
|
||||
*
|
||||
* @param fileName absolute file name of the archive to install
|
||||
* @param modName suggested name of the mod. If this is empty (the default), a name will be guessed based on the filename. The user will always have a chance to rename the mod
|
||||
* @return true if the archive was installed, false if installation failed or was refused
|
||||
* @exception std::exception an exception may be thrown if the archive can't be opened (maybe the format is invalid or the file is damaged)
|
||||
**/
|
||||
bool install(const QString &fileName, MOBase::GuessedValue<QString> &modName, bool &hasIniTweaks);
|
||||
|
||||
/**
|
||||
* @return true if the installation was canceled
|
||||
**/
|
||||
bool wasCancelled();
|
||||
|
||||
/**
|
||||
* @brief retrieve a string describing the specified error code
|
||||
*
|
||||
* @param errorCode an error code as returned by the archiving function
|
||||
* @return the error string
|
||||
* @todo This function doesn't belong here, it is only public because the SelfUpdater class also uses "Archive" to get to the package.txt file
|
||||
**/
|
||||
static QString getErrorString(Archive::Error errorCode);
|
||||
|
||||
/**
|
||||
* @brief register an installer-plugin
|
||||
* @param the installer to register
|
||||
*/
|
||||
void registerInstaller(MOBase::IPluginInstaller *installer);
|
||||
|
||||
/**
|
||||
* @return list of file extensions we can install
|
||||
*/
|
||||
QStringList getSupportedExtensions() const;
|
||||
|
||||
/**
|
||||
* @brief extract the specified file from the currently open archive to a temporary location
|
||||
* @param (relative) name of the file within the archive
|
||||
* @return the absolute name of the temporary file
|
||||
* @note the call will fail with an exception if no archive is open (plugins deriving
|
||||
* from IPluginInstallerSimple can rely on that, custom installers shouldn't)
|
||||
* @note the temporary file is automatically cleaned up after the installation
|
||||
* @note This call can be very slow if the archive is large and "solid"
|
||||
*/
|
||||
virtual QString extractFile(const QString &fileName);
|
||||
|
||||
/**
|
||||
* @brief extract the specified files from the currently open archive to a temporary location
|
||||
* @param (relative) names of files within the archive
|
||||
* @return the absolute names of the temporary files
|
||||
* @note the call will fail with an exception if no archive is open (plugins deriving
|
||||
* from IPluginInstallerSimple can rely on that, custom installers shouldn't)
|
||||
* @note the temporary file is automatically cleaned up after the installation
|
||||
* @note This call can be very slow if the archive is large and "solid"
|
||||
*/
|
||||
virtual QStringList extractFiles(const QStringList &files, bool flatten);
|
||||
|
||||
/**
|
||||
* @brief installs an archive
|
||||
* @param modName suggested name of the mod
|
||||
* @param archiveFile path to the archive to install
|
||||
* @return the installation result
|
||||
*/
|
||||
virtual MOBase::IPluginInstaller::EInstallResult installArchive(MOBase::GuessedValue<QString> &modName, const QString &archiveName);
|
||||
|
||||
/**
|
||||
* @brief test if the specified mod name is free. If not, query the user how to proceed
|
||||
* @param modName current possible names for the mod
|
||||
* @param merge if this value is not null, the value will be set to whether the use chose to merge or replace
|
||||
* @return true if we can proceed with the installation, false if the user canceled or in case of an unrecoverable error
|
||||
*/
|
||||
virtual bool testOverwrite(MOBase::GuessedValue<QString> &modName, bool *merge = nullptr) const;
|
||||
|
||||
private:
|
||||
|
||||
void queryPassword(QString *password);
|
||||
void updateProgress(float percentage);
|
||||
void updateProgressFile(const QString &fileName);
|
||||
void report7ZipError(const QString &errorMessage);
|
||||
|
||||
MOBase::DirectoryTree *createFilesTree();
|
||||
|
||||
// remap all files in the archive to the directory structure represented by baseNode
|
||||
// files not present in baseNode are disabled
|
||||
void mapToArchive(const MOBase::DirectoryTree::Node *baseNode);
|
||||
|
||||
// recursive worker function for mapToArchive
|
||||
void mapToArchive(const MOBase::DirectoryTree::Node *node, QString path, FileData * const *data);
|
||||
bool unpackSingleFile(const QString &fileName);
|
||||
|
||||
|
||||
bool isSimpleArchiveTopLayer(const MOBase::DirectoryTree::Node *node, bool bainStyle);
|
||||
MOBase::DirectoryTree::Node *getSimpleArchiveBase(MOBase::DirectoryTree *dataTree);
|
||||
|
||||
bool doInstall(MOBase::GuessedValue<QString> &modName, QString gameName,
|
||||
int modID, const QString &version, const QString &newestVersion, int categoryID, const QString &repository);
|
||||
|
||||
QString generateBackupName(const QString &directoryName) const;
|
||||
|
||||
bool ensureValidModName(MOBase::GuessedValue<QString> &name) const;
|
||||
|
||||
void postInstallCleanup();
|
||||
|
||||
signals:
|
||||
|
||||
void progressUpdate(float percentage);
|
||||
void progressUpdate(QString const fileName);
|
||||
|
||||
private:
|
||||
|
||||
struct ByPriority {
|
||||
bool operator()(MOBase::IPluginInstaller *LHS, MOBase::IPluginInstaller *RHS) const
|
||||
{
|
||||
return LHS->priority() > RHS->priority();
|
||||
}
|
||||
};
|
||||
|
||||
struct CaseInsensitive {
|
||||
bool operator() (const QString &LHS, const QString &RHS) const
|
||||
{
|
||||
return QString::compare(LHS, RHS, Qt::CaseInsensitive) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
QWidget *m_ParentWidget;
|
||||
|
||||
QString m_ModsDirectory;
|
||||
QString m_DownloadsDirectory;
|
||||
|
||||
std::vector<MOBase::IPluginInstaller*> m_Installers;
|
||||
std::set<QString, CaseInsensitive> m_SupportedExtensions;
|
||||
|
||||
Archive *m_ArchiveHandler;
|
||||
QString m_CurrentFile;
|
||||
|
||||
QProgressDialog *m_InstallationProgress { nullptr };
|
||||
int m_Progress;
|
||||
QString m_ProgressFile;
|
||||
|
||||
std::set<QString> m_TempFilesToDelete;
|
||||
|
||||
QString m_URL;
|
||||
};
|
||||
|
||||
|
||||
#endif // INSTALLATIONMANAGER_H
|
||||
/*
|
||||
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 INSTALLATIONMANAGER_H
|
||||
#define INSTALLATIONMANAGER_H
|
||||
|
||||
|
||||
#include <iinstallationmanager.h>
|
||||
#include <iplugininstaller.h>
|
||||
#include <guessedvalue.h>
|
||||
|
||||
#include <QObject>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <archive.h>
|
||||
#include <QProgressDialog>
|
||||
#include <set>
|
||||
#include <errorcodes.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief manages the installation of mod archives
|
||||
* This currently supports two special kind of archives:
|
||||
* - "simple" archives: properly packaged archives without options, so they can be extracted to the (virtual) data directory directly
|
||||
* - "complex" bain archives: archives with options for the bain system.
|
||||
* All other archives are managed through the manual "InstallDialog"
|
||||
* @todo this may be a good place to support plugins
|
||||
**/
|
||||
class InstallationManager : public QObject, public MOBase::IInstallationManager
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
*
|
||||
* @param parent parent object.
|
||||
**/
|
||||
explicit InstallationManager();
|
||||
|
||||
virtual ~InstallationManager();
|
||||
|
||||
void setParentWidget(QWidget *widget);
|
||||
|
||||
void setURL(const QString &url);
|
||||
|
||||
/**
|
||||
* @brief update the directory where mods are to be installed
|
||||
* @param modsDirectory the mod directory
|
||||
* @note this is called a lot, probably redundantly
|
||||
*/
|
||||
void setModsDirectory(const QString &modsDirectory) { m_ModsDirectory = modsDirectory; }
|
||||
|
||||
/**
|
||||
* @brief update the directory where downloads are stored
|
||||
* @param downloadDirectory the download directory
|
||||
*/
|
||||
void setDownloadDirectory(const QString &downloadDirectory) { m_DownloadsDirectory = downloadDirectory; }
|
||||
|
||||
/**
|
||||
* @brief install a mod from an archive
|
||||
*
|
||||
* @param fileName absolute file name of the archive to install
|
||||
* @param modName suggested name of the mod. If this is empty (the default), a name will be guessed based on the filename. The user will always have a chance to rename the mod
|
||||
* @return true if the archive was installed, false if installation failed or was refused
|
||||
* @exception std::exception an exception may be thrown if the archive can't be opened (maybe the format is invalid or the file is damaged)
|
||||
**/
|
||||
bool install(const QString &fileName, MOBase::GuessedValue<QString> &modName, bool &hasIniTweaks, int modID = 0);
|
||||
|
||||
/**
|
||||
* @return true if the installation was canceled
|
||||
**/
|
||||
bool wasCancelled();
|
||||
|
||||
/**
|
||||
* @brief retrieve a string describing the specified error code
|
||||
*
|
||||
* @param errorCode an error code as returned by the archiving function
|
||||
* @return the error string
|
||||
* @todo This function doesn't belong here, it is only public because the SelfUpdater class also uses "Archive" to get to the package.txt file
|
||||
**/
|
||||
static QString getErrorString(Archive::Error errorCode);
|
||||
|
||||
/**
|
||||
* @brief register an installer-plugin
|
||||
* @param the installer to register
|
||||
*/
|
||||
void registerInstaller(MOBase::IPluginInstaller *installer);
|
||||
|
||||
/**
|
||||
* @return list of file extensions we can install
|
||||
*/
|
||||
QStringList getSupportedExtensions() const;
|
||||
|
||||
/**
|
||||
* @brief extract the specified file from the currently open archive to a temporary location
|
||||
* @param (relative) name of the file within the archive
|
||||
* @return the absolute name of the temporary file
|
||||
* @note the call will fail with an exception if no archive is open (plugins deriving
|
||||
* from IPluginInstallerSimple can rely on that, custom installers shouldn't)
|
||||
* @note the temporary file is automatically cleaned up after the installation
|
||||
* @note This call can be very slow if the archive is large and "solid"
|
||||
*/
|
||||
virtual QString extractFile(const QString &fileName);
|
||||
|
||||
/**
|
||||
* @brief extract the specified files from the currently open archive to a temporary location
|
||||
* @param (relative) names of files within the archive
|
||||
* @return the absolute names of the temporary files
|
||||
* @note the call will fail with an exception if no archive is open (plugins deriving
|
||||
* from IPluginInstallerSimple can rely on that, custom installers shouldn't)
|
||||
* @note the temporary file is automatically cleaned up after the installation
|
||||
* @note This call can be very slow if the archive is large and "solid"
|
||||
*/
|
||||
virtual QStringList extractFiles(const QStringList &files, bool flatten);
|
||||
|
||||
/**
|
||||
* @brief installs an archive
|
||||
* @param modName suggested name of the mod
|
||||
* @param archiveFile path to the archive to install
|
||||
* @return the installation result
|
||||
*/
|
||||
virtual MOBase::IPluginInstaller::EInstallResult installArchive(MOBase::GuessedValue<QString> &modName, const QString &archiveName, const int &modId = 0);
|
||||
|
||||
/**
|
||||
* @brief test if the specified mod name is free. If not, query the user how to proceed
|
||||
* @param modName current possible names for the mod
|
||||
* @param merge if this value is not null, the value will be set to whether the use chose to merge or replace
|
||||
* @return true if we can proceed with the installation, false if the user canceled or in case of an unrecoverable error
|
||||
*/
|
||||
virtual bool testOverwrite(MOBase::GuessedValue<QString> &modName, bool *merge = nullptr) const;
|
||||
|
||||
QString generateBackupName(const QString &directoryName) const;
|
||||
|
||||
private:
|
||||
|
||||
void queryPassword(QString *password);
|
||||
void updateProgress(float percentage);
|
||||
void updateProgressFile(const QString &fileName);
|
||||
void report7ZipError(const QString &errorMessage);
|
||||
|
||||
MOBase::DirectoryTree *createFilesTree();
|
||||
|
||||
// remap all files in the archive to the directory structure represented by baseNode
|
||||
// files not present in baseNode are disabled
|
||||
void mapToArchive(const MOBase::DirectoryTree::Node *baseNode);
|
||||
|
||||
// recursive worker function for mapToArchive
|
||||
void mapToArchive(const MOBase::DirectoryTree::Node *node, QString path, FileData * const *data);
|
||||
bool unpackSingleFile(const QString &fileName);
|
||||
|
||||
|
||||
bool isSimpleArchiveTopLayer(const MOBase::DirectoryTree::Node *node, bool bainStyle);
|
||||
MOBase::DirectoryTree::Node *getSimpleArchiveBase(MOBase::DirectoryTree *dataTree);
|
||||
|
||||
bool doInstall(MOBase::GuessedValue<QString> &modName, QString gameName,
|
||||
int modID, const QString &version, const QString &newestVersion, int categoryID, const QString &repository);
|
||||
|
||||
//QString generateBackupName(const QString &directoryName) const;
|
||||
|
||||
bool ensureValidModName(MOBase::GuessedValue<QString> &name) const;
|
||||
|
||||
void postInstallCleanup();
|
||||
|
||||
signals:
|
||||
|
||||
void progressUpdate(float percentage);
|
||||
void progressUpdate(QString const fileName);
|
||||
|
||||
private:
|
||||
|
||||
struct ByPriority {
|
||||
bool operator()(MOBase::IPluginInstaller *LHS, MOBase::IPluginInstaller *RHS) const
|
||||
{
|
||||
return LHS->priority() > RHS->priority();
|
||||
}
|
||||
};
|
||||
|
||||
struct CaseInsensitive {
|
||||
bool operator() (const QString &LHS, const QString &RHS) const
|
||||
{
|
||||
return QString::compare(LHS, RHS, Qt::CaseInsensitive) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
QWidget *m_ParentWidget;
|
||||
|
||||
QString m_ModsDirectory;
|
||||
QString m_DownloadsDirectory;
|
||||
|
||||
std::vector<MOBase::IPluginInstaller*> m_Installers;
|
||||
std::set<QString, CaseInsensitive> m_SupportedExtensions;
|
||||
|
||||
Archive *m_ArchiveHandler;
|
||||
QString m_CurrentFile;
|
||||
QString m_ErrorMessage;
|
||||
|
||||
QProgressDialog *m_InstallationProgress { nullptr };
|
||||
int m_Progress;
|
||||
QString m_ProgressFile;
|
||||
|
||||
std::set<QString> m_TempFilesToDelete;
|
||||
|
||||
QString m_URL;
|
||||
};
|
||||
|
||||
|
||||
#endif // INSTALLATIONMANAGER_H
|
||||
|
||||
@@ -66,6 +66,7 @@ void InstanceManager::clearCurrentInstance()
|
||||
{
|
||||
setCurrentInstance("");
|
||||
m_Reset = true;
|
||||
m_overrideInstance = false;
|
||||
}
|
||||
|
||||
void InstanceManager::setCurrentInstance(const QString &name)
|
||||
@@ -136,12 +137,13 @@ QString InstanceManager::queryInstanceName(const QStringList &instanceList) cons
|
||||
QInputDialog dialog;
|
||||
|
||||
dialog.setWindowTitle(QObject::tr("Enter a Name for the new Instance"));
|
||||
dialog.setLabelText(QObject::tr("Enter a new name or select one from the suggested list:"));
|
||||
dialog.setLabelText(QObject::tr("Enter a new name or select one from the suggested list: \n"
|
||||
"(This is just the name of the Instance, not the game selection)"));
|
||||
// would be neat if we could take the names from the game plugins but
|
||||
// the required initialization order requires the ini file to be
|
||||
// available *before* we load plugins
|
||||
dialog.setComboBoxItems({ "NewName", "Fallout 4", "SkyrimSE", "Skyrim", "Fallout 3",
|
||||
"Fallout NV", "FO4VR", "Oblivion" });
|
||||
dialog.setComboBoxItems({ "NewName", "Fallout 4", "SkyrimSE", "Skyrim", "SkyrimVR", "Fallout 3",
|
||||
"Fallout NV", "TTW", "FO4VR", "Oblivion", "Morrowind" });
|
||||
dialog.setComboBoxEditable(true);
|
||||
|
||||
if (dialog.exec() == QDialog::Rejected) {
|
||||
@@ -324,4 +326,4 @@ QString InstanceManager::sanitizeInstanceName(const QString &name) const
|
||||
return sanitizeInstanceName(new_name);
|
||||
}
|
||||
return new_name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <ipluginmodpage.h>
|
||||
#include <delayedfilewriter.h>
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
class QSettings;
|
||||
|
||||
class IUserInterface
|
||||
@@ -16,7 +18,8 @@ public:
|
||||
|
||||
virtual void storeSettings(QSettings &settings) = 0;
|
||||
|
||||
virtual void registerPluginTool(MOBase::IPluginTool *tool) = 0;
|
||||
virtual void registerPluginTool(MOBase::IPluginTool *tool, QString name = QString(), QMenu *menu = nullptr) = 0;
|
||||
virtual void registerPluginTools(std::vector<MOBase::IPluginTool *> toolPlugins) = 0;
|
||||
virtual void registerModPage(MOBase::IPluginModPage *modPage) = 0;
|
||||
|
||||
virtual void installTranslator(const QString &name) = 0;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
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 "listdialog.h"
|
||||
#include "ui_listdialog.h"
|
||||
|
||||
ListDialog::ListDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::ListDialog)
|
||||
, m_Choices()
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->filterEdit->setFocus();
|
||||
}
|
||||
|
||||
ListDialog::~ListDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ListDialog::setChoices(QStringList choices)
|
||||
{
|
||||
m_Choices = choices;
|
||||
ui->choiceList->clear();
|
||||
ui->choiceList->addItems(m_Choices);
|
||||
}
|
||||
|
||||
QString ListDialog::getChoice() const
|
||||
{
|
||||
if (ui->choiceList->selectedItems().length()) {
|
||||
return ui->choiceList->currentItem()->text();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void ListDialog::on_filterEdit_textChanged(QString filter)
|
||||
{
|
||||
QStringList newChoices;
|
||||
for (auto choice : m_Choices) {
|
||||
if (choice.contains(filter, Qt::CaseInsensitive)){
|
||||
newChoices << choice;
|
||||
}
|
||||
}
|
||||
ui->choiceList->clear();
|
||||
ui->choiceList->addItems(newChoices);
|
||||
|
||||
if (newChoices.length() == 1) {
|
||||
QListWidgetItem *item = ui->choiceList->item(0);
|
||||
ui->choiceList->setItemSelected(item, true);
|
||||
ui->choiceList->setCurrentItem(item);
|
||||
}
|
||||
|
||||
if (!filter.isEmpty()) {
|
||||
ui->choiceList->setStyleSheet("QListWidget { border: 2px ridge #f00; }");
|
||||
} else {
|
||||
ui->choiceList->setStyleSheet("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef LISTDIALOG_H
|
||||
#define LISTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class ListDialog;
|
||||
}
|
||||
|
||||
class ListDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ListDialog(QWidget *parent = nullptr);
|
||||
~ListDialog();
|
||||
|
||||
void setChoices(QStringList choices);
|
||||
QString getChoice() const;
|
||||
|
||||
public slots:
|
||||
void on_filterEdit_textChanged(QString filter);
|
||||
|
||||
private:
|
||||
Ui::ListDialog *ui;
|
||||
QStringList m_Choices;
|
||||
};
|
||||
|
||||
#endif // LISTDIALOG_H
|
||||
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ListDialog</class>
|
||||
<widget class="QDialog" name="ListDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>260</width>
|
||||
<height>380</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Select an item...</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="choiceList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>240</width>
|
||||
<height>280</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MOBase::LineEditClear" name="filterEdit">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MOBase::LineEditClear</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>lineeditclear.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ListDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ListDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
+3
-2
@@ -322,7 +322,7 @@ MOBase::IPluginGame *determineCurrentGame(QString const &moPath, QSettings &sett
|
||||
|
||||
//The following code would try to determine the right game to mange but it would usually find the wrong one
|
||||
//so it was commented out.
|
||||
/*
|
||||
/*
|
||||
//OK, we are in a new setup or existing info is useless.
|
||||
//See if MO has been installed inside a game directory
|
||||
for (IPluginGame * const game : plugins.plugins<IPluginGame>()) {
|
||||
@@ -383,7 +383,7 @@ MOBase::IPluginGame *determineCurrentGame(QString const &moPath, QSettings &sett
|
||||
}
|
||||
}
|
||||
reportError(QObject::tr("No game identified in \"%1\". The directory is required to contain "
|
||||
"the game binary and its launcher.").arg(gamePath));
|
||||
"the game binary.").arg(gamePath));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,5 +715,6 @@ int main(int argc, char *argv[])
|
||||
return result;
|
||||
}
|
||||
argc = 1;
|
||||
moshortcut = MOShortcut("");
|
||||
} while (true);
|
||||
}
|
||||
|
||||
+735
-109
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