mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7665d9dd61 | ||
|
|
12104ed988 |
@@ -7,7 +7,7 @@ on:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
env:
|
||||
VCPKG_BINARY_SOURCES: ${{ vars.AZ_BLOB_VCPKG_URL != '' && format('clear;x-azblob,{0},{1},readwrite', vars.AZ_BLOB_VCPKG_URL, secrets.AZ_BLOB_SAS) || '' }}
|
||||
VCPKG_BINARY_SOURCES: clear;x-azblob,${{ vars.AZ_BLOB_VCPKG_URL }},${{ secrets.AZ_BLOB_SAS }},readwrite
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
id: build-modorganizer
|
||||
uses: ModOrganizer2/build-with-mob-action@master
|
||||
with:
|
||||
qt-modules: qtpositioning qtwebchannel qtwebengine qtwebsockets qtnetworkauth
|
||||
qt-modules: qtpositioning qtwebchannel qtwebengine qtwebsockets
|
||||
mo2-dependencies: usvfs uibase bsatk esptk archive lootcli
|
||||
|
||||
- name: Install ModOrganizer
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v6.0.0
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-merge-conflict
|
||||
- id: check-case-conflict
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v22.1.2
|
||||
rev: v19.1.5
|
||||
hooks:
|
||||
- id: clang-format
|
||||
'types_or': [c++, c]
|
||||
|
||||
+2
-3
@@ -3,11 +3,10 @@ cmake_minimum_required(VERSION 3.16)
|
||||
# TODO: clean include directives
|
||||
set(MO2_CMAKE_DEPRECATED_UIBASE_INCLUDE ON)
|
||||
|
||||
# Remove tutorials until Qt is fixed
|
||||
set(MO2_SKIP_TUTORIALS_INSTALL ON)
|
||||
|
||||
project(organizer)
|
||||
|
||||
find_package(mo2-cmake CONFIG REQUIRED)
|
||||
|
||||
# if MO2_INSTALL_IS_BIN is set, this means that we should install directly into the
|
||||
# installation prefix, without the bin/ subfolder, typically for a standalone build
|
||||
# to update an existing install
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
find_package(mo2-cmake CONFIG REQUIRED)
|
||||
|
||||
find_package(usvfs CONFIG REQUIRED)
|
||||
|
||||
@@ -109,7 +108,6 @@ mo2_add_filter(NAME src/application GROUPS
|
||||
multiprocess
|
||||
sanitychecks
|
||||
selfupdater
|
||||
systemtraymanager
|
||||
updatedialog
|
||||
)
|
||||
|
||||
@@ -274,9 +272,7 @@ mo2_add_filter(NAME src/profiles GROUPS
|
||||
|
||||
mo2_add_filter(NAME src/proxies GROUPS
|
||||
downloadmanagerproxy
|
||||
executableslistproxy
|
||||
gamefeaturesproxy
|
||||
instancemanagerproxy
|
||||
modlistproxy
|
||||
organizerproxy
|
||||
pluginlistproxy
|
||||
|
||||
@@ -45,6 +45,7 @@ AboutDialog::AboutDialog(const QString& version, QWidget* parent)
|
||||
m_LicenseFiles[LICENSE_CCBY3] = "BY-SA-v3.0.txt";
|
||||
m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt";
|
||||
m_LicenseFiles[LICENSE_PYTHON] = "python.txt";
|
||||
m_LicenseFiles[LICENSE_SSL] = "openssl.txt";
|
||||
m_LicenseFiles[LICENSE_CPPTOML] = "cpptoml.txt";
|
||||
m_LicenseFiles[LICENSE_UDIS] = "udis86.txt";
|
||||
m_LicenseFiles[LICENSE_SPDLOG] = "spdlog.txt";
|
||||
@@ -68,6 +69,7 @@ AboutDialog::AboutDialog(const QString& version, QWidget* parent)
|
||||
addLicense("ANTLR", LICENSE_ANTLR);
|
||||
addLicense("LOOT", LICENSE_GPL3);
|
||||
addLicense("Python", LICENSE_PYTHON);
|
||||
addLicense("OpenSSL", LICENSE_SSL);
|
||||
addLicense("cpptoml", LICENSE_CPPTOML);
|
||||
addLicense("Udis86", LICENSE_UDIS);
|
||||
addLicense("spdlog", LICENSE_SPDLOG);
|
||||
|
||||
@@ -51,6 +51,7 @@ private:
|
||||
LICENSE_BOOST,
|
||||
LICENSE_CCBY3,
|
||||
LICENSE_PYTHON,
|
||||
LICENSE_SSL,
|
||||
LICENSE_CPPTOML,
|
||||
LICENSE_7ZIP,
|
||||
LICENSE_ZLIB,
|
||||
|
||||
+14
-169
@@ -127,7 +127,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string notr="true"><html><head/><body><p>Copyright © 2011-2016 Sebastian Herbord<br/>Copyright © 2016-2026 Mod Organizer 2 Contributors</p></body></html></string>
|
||||
<string notr="true"><html><head/><body><p>Copyright © 2011-2016 Sebastian Herbord<br/>Copyright © 2016-2025 Mod Organizer 2 Contributors</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -222,7 +222,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Holt59</string>
|
||||
<string>Holt59</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -484,21 +484,6 @@
|
||||
<string notr="true">6788</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">AkiraJkr</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">AmeliaCute</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ashemedai</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">blacksol</string>
|
||||
@@ -519,16 +504,6 @@
|
||||
<string notr="true">Brixified</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">CheffieGithub</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">daescha</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ddbb07</string>
|
||||
@@ -539,31 +514,11 @@
|
||||
<string notr="true">deathneko11</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Deewens</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">DefinitelyNotSade</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">dekart811</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Deorder</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">diegofesanto</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">DoubleYou</string>
|
||||
@@ -574,11 +529,6 @@
|
||||
<string notr="true">Drew Warwick</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Eddoursul</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">erri120</string>
|
||||
@@ -629,66 +579,11 @@
|
||||
<string notr="true">jimfcarroll</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Jonny_Bro</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ju5tA1ex</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Kane Dou</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">KenJyn76</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Ketsuban</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">LaughingHyena</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Luca|EzioTheDeadPoet</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">mick-lue</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ModZero</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">mopioid</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">mrudat</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Nikirack</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ogrotten</string>
|
||||
@@ -704,96 +599,36 @@
|
||||
<string notr="true">Patchier</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Paynamia</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">PurpleFez</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Ra2-IFV</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">reedts</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">RodolfoFigueroa</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Ryan Young</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Schilduin</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">shellbj</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">SuperSandro2000</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Syer10</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">The Conceptionist</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">TheForgotten69</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">TheUnlocked</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">thosrtanner</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Trosski</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Twinki</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Uhuru</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">uwx</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Wolverine2710</string>
|
||||
@@ -801,7 +636,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">xieve</string>
|
||||
<string notr="true">thosrtanner</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
@@ -811,7 +646,17 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Zash</string>
|
||||
<string notr="true">Eddoursul</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">Twinki</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">ashemedai</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
|
||||
@@ -17,8 +17,8 @@ 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 ARCHIVEFILETREE_H
|
||||
#define ARCHIVEFILETREE_H
|
||||
#ifndef ARCHIVEFILENETRY_H
|
||||
#define ARCHIVEFILENTRY_H
|
||||
|
||||
#include <archive/archive.h>
|
||||
#include <uibase/ifiletree.h>
|
||||
|
||||
+6
-49
@@ -10,8 +10,6 @@
|
||||
#include <log.h>
|
||||
#include <report.h>
|
||||
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
|
||||
namespace cl
|
||||
{
|
||||
|
||||
@@ -223,12 +221,8 @@ std::optional<int> CommandLine::runEarly()
|
||||
|
||||
std::optional<int> CommandLine::runPostApplication(MOApplication& a)
|
||||
{
|
||||
const auto instanceArg = m_vm.find("instance");
|
||||
if (instanceArg != m_vm.end() &&
|
||||
!instanceArg->second.as<boost::optional<std::string>>().has_value()) {
|
||||
|
||||
// handle -i with no arguments (distinct from -i "", which will launch the
|
||||
// portable instance if it exists, hence the use of boost::optional)
|
||||
// handle -i with no arguments
|
||||
if (m_vm.count("instance") && m_vm["instance"].as<std::string>() == "") {
|
||||
env::Console c;
|
||||
|
||||
if (auto i = InstanceManager::singleton().currentInstance()) {
|
||||
@@ -320,9 +314,7 @@ void CommandLine::createOptions()
|
||||
|
||||
("logs", "duplicates the logs to stdout")
|
||||
|
||||
("instance,i",
|
||||
po::value<boost::optional<std::string>>()->implicit_value(
|
||||
boost::none),
|
||||
("instance,i", po::value<std::string>()->implicit_value(""),
|
||||
"use the given instance (defaults to last used)")
|
||||
|
||||
("profile,p", po::value<std::string>(),
|
||||
@@ -410,14 +402,8 @@ std::optional<QString> CommandLine::instance() const
|
||||
|
||||
if (m_shortcut.isValid() && m_shortcut.hasInstance()) {
|
||||
return m_shortcut.instanceName();
|
||||
} else {
|
||||
const auto instanceArg = m_vm.find("instance");
|
||||
if (instanceArg != m_vm.end()) {
|
||||
const auto& instanceVal = instanceArg->second.as<boost::optional<std::string>>();
|
||||
if (instanceVal.has_value()) {
|
||||
return QString::fromStdString(instanceVal.value());
|
||||
}
|
||||
}
|
||||
} else if (m_vm.count("instance")) {
|
||||
return QString::fromStdString(m_vm["instance"].as<std::string>());
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -853,18 +839,6 @@ Command::Meta DownloadFileCommand::meta() const
|
||||
return {"download", "downloads a file", "URL", ""};
|
||||
}
|
||||
|
||||
po::options_description DownloadFileCommand::getVisibleOptions() const
|
||||
{
|
||||
po::options_description d;
|
||||
|
||||
d.add_options()("name,n", po::value<std::string>(), "(optional) the download name")(
|
||||
"modname,m", po::value<std::string>(), "(optional) the mod name")(
|
||||
"version,v", po::value<std::string>(), "(optional) the download / mod version")(
|
||||
"source,s", po::value<std::string>(), "(optional) the download source");
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
po::options_description DownloadFileCommand::getInternalOptions() const
|
||||
{
|
||||
po::options_description d;
|
||||
@@ -891,33 +865,16 @@ bool DownloadFileCommand::canForwardToPrimary() const
|
||||
std::optional<int> DownloadFileCommand::runPostOrganizer(OrganizerCore& core)
|
||||
{
|
||||
const QString url = QString::fromStdString(vm()["URL"].as<std::string>());
|
||||
QString name, modName, version, source;
|
||||
|
||||
if (!url.startsWith("https://")) {
|
||||
reportError(QObject::tr("Download URL must start with https://"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm().count("name")) {
|
||||
name = QString::fromStdString(vm()["name"].as<std::string>());
|
||||
}
|
||||
|
||||
if (vm().count("modname")) {
|
||||
modName = QString::fromStdString(vm()["modname"].as<std::string>());
|
||||
}
|
||||
|
||||
if (vm().count("version")) {
|
||||
version = QString::fromStdString(vm()["version"].as<std::string>());
|
||||
}
|
||||
|
||||
if (vm().count("source")) {
|
||||
source = QString::fromStdString(vm()["source"].as<std::string>());
|
||||
}
|
||||
|
||||
log::debug("starting direct download from command line: {}", url.toStdString());
|
||||
MessageDialog::showMessage(QObject::tr("Download started"), qApp->activeWindow(),
|
||||
false);
|
||||
core.downloadManager()->startDownloadURLWithMeta(url, name, modName, version, source);
|
||||
core.downloadManager()->startDownloadURLs(QStringList() << url);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -212,7 +212,6 @@ class DownloadFileCommand : public Command
|
||||
protected:
|
||||
Meta meta() const override;
|
||||
|
||||
po::options_description getVisibleOptions() const override;
|
||||
po::options_description getInternalOptions() const override;
|
||||
po::positional_options_description getPositional() const override;
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
<file name="dxcompiler.dll" />
|
||||
<file name="dxil.dll" />
|
||||
<file name="libbsarchd.dll" />
|
||||
<file name="libcrypto-3-x64.dll" />
|
||||
<file name="liblz4.dll" />
|
||||
<file name="libssl-3-x64.dll" />
|
||||
<file name="opengl32sw.dll" />
|
||||
<file name="Qt6Concurrentd.dll" />
|
||||
<file name="Qt6Cored.dll" />
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
<file name="dxcompiler.dll" />
|
||||
<file name="dxil.dll" />
|
||||
<file name="libbsarch.dll" />
|
||||
<file name="libcrypto-3-x64.dll" />
|
||||
<file name="liblz4.dll" />
|
||||
<file name="libssl-3-x64.dll" />
|
||||
<file name="opengl32sw.dll" />
|
||||
<file name="Qt6Concurrent.dll" />
|
||||
<file name="Qt6Core.dll" />
|
||||
|
||||
+8
-13
@@ -35,10 +35,8 @@ DownloadList::DownloadList(OrganizerCore& core, QObject* parent)
|
||||
: QAbstractTableModel(parent), m_manager(*core.downloadManager()),
|
||||
m_settings(core.settings())
|
||||
{
|
||||
connect(&m_manager, &DownloadManager::aboutToResetModel, this,
|
||||
&DownloadList::onAboutToResetModel);
|
||||
connect(&m_manager, &DownloadManager::modelReset, this, &DownloadList::onModelReset);
|
||||
connect(&m_manager, &DownloadManager::rowChanged, this, &DownloadList::onRowChanged);
|
||||
connect(&m_manager, SIGNAL(update(int)), this, SLOT(update(int)));
|
||||
connect(&m_manager, SIGNAL(aboutToUpdate()), this, SLOT(aboutToUpdate()));
|
||||
}
|
||||
|
||||
int DownloadList::rowCount(const QModelIndex& parent) const
|
||||
@@ -241,19 +239,16 @@ QVariant DownloadList::data(const QModelIndex& index, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void DownloadList::onAboutToResetModel()
|
||||
void DownloadList::aboutToUpdate()
|
||||
{
|
||||
beginResetModel();
|
||||
emit beginResetModel();
|
||||
}
|
||||
|
||||
void DownloadList::onModelReset()
|
||||
void DownloadList::update(int row)
|
||||
{
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void DownloadList::onRowChanged(int row)
|
||||
{
|
||||
if (row < this->rowCount())
|
||||
if (row < 0)
|
||||
emit endResetModel();
|
||||
else if (row < this->rowCount())
|
||||
emit dataChanged(
|
||||
this->index(row, 0, QModelIndex()),
|
||||
this->index(row, this->columnCount(QModelIndex()) - 1, QModelIndex()));
|
||||
|
||||
+7
-11
@@ -83,20 +83,16 @@ public:
|
||||
//
|
||||
bool lessThanPredicate(const QModelIndex& left, const QModelIndex& right);
|
||||
|
||||
private slots:
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* @brief full reset (row count changed). Drops selection and scroll state.
|
||||
*/
|
||||
void onAboutToResetModel();
|
||||
void onModelReset();
|
||||
|
||||
/**
|
||||
* @brief single-row data change (row count unchanged). Preserves view state.
|
||||
* @brief used to inform the model that data has changed
|
||||
*
|
||||
* @param row the row that changed
|
||||
*/
|
||||
void onRowChanged(int row);
|
||||
* @param row the row that changed. This can be negative to update the whole view
|
||||
**/
|
||||
void update(int row);
|
||||
|
||||
void aboutToUpdate();
|
||||
|
||||
private:
|
||||
DownloadManager& m_manager;
|
||||
|
||||
@@ -231,18 +231,14 @@ void DownloadListView::onCustomContextMenu(const QPoint& point)
|
||||
menu.addAction(tr("Install"), [=] {
|
||||
issueInstall(row);
|
||||
});
|
||||
if (m_Manager->isInfoIncomplete(row)) {
|
||||
if (m_Manager->isInfoIncomplete(row))
|
||||
menu.addAction(tr("Query Info"), [=] {
|
||||
issueQueryInfoMd5(row);
|
||||
});
|
||||
} else {
|
||||
else
|
||||
menu.addAction(tr("Visit on Nexus"), [=] {
|
||||
issueVisitOnNexus(row);
|
||||
});
|
||||
menu.addAction(tr("Visit the uploader's profile"), [=] {
|
||||
issueVisitUploaderProfile(row);
|
||||
});
|
||||
}
|
||||
menu.addAction(tr("Open File"), [=] {
|
||||
issueOpenFile(row);
|
||||
});
|
||||
@@ -333,7 +329,7 @@ void DownloadListView::keyPressEvent(QKeyEvent* event)
|
||||
const int row = qobject_cast<QSortFilterProxyModel*>(model())
|
||||
->mapToSource(currentIndex())
|
||||
.row();
|
||||
auto state = m_Manager->getState(row);
|
||||
auto state = m_Manager->getState(row);
|
||||
if (state >= DownloadManager::STATE_READY) {
|
||||
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
|
||||
issueInstall(row);
|
||||
@@ -412,11 +408,6 @@ void DownloadListView::issueVisitOnNexus(int index)
|
||||
emit visitOnNexus(index);
|
||||
}
|
||||
|
||||
void DownloadListView::issueVisitUploaderProfile(int index)
|
||||
{
|
||||
emit visitUploaderProfile(index);
|
||||
}
|
||||
|
||||
void DownloadListView::issueOpenFile(int index)
|
||||
{
|
||||
emit openFile(index);
|
||||
|
||||
@@ -87,7 +87,6 @@ signals:
|
||||
void pauseDownload(int index);
|
||||
void resumeDownload(int index);
|
||||
void visitOnNexus(int index);
|
||||
void visitUploaderProfile(int index);
|
||||
void openFile(int index);
|
||||
void openMetaFile(int index);
|
||||
void openInDownloadsFolder(int index);
|
||||
@@ -106,7 +105,6 @@ private slots:
|
||||
void issueRestoreToView(int index);
|
||||
void issueRestoreToViewAll();
|
||||
void issueVisitOnNexus(int index);
|
||||
void issueVisitUploaderProfile(int index);
|
||||
void issueOpenFile(int index);
|
||||
void issueOpenMetaFile(int index);
|
||||
void issueOpenInDownloadsFolder(int index);
|
||||
|
||||
+245
-271
File diff suppressed because it is too large
Load Diff
+41
-114
@@ -52,58 +52,6 @@ class NexusInterface;
|
||||
class PluginContainer;
|
||||
class OrganizerCore;
|
||||
|
||||
/**
|
||||
* @brief QFileSystemWatcher with a nestable RAII suspension scope.
|
||||
*
|
||||
* Forwards directoryChanged() only while no Guard is alive. Use a Guard to
|
||||
* bracket filesystem writes that would otherwise trigger a spurious refresh.
|
||||
*/
|
||||
class DirWatcherManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DirWatcherManager(QObject* parent = nullptr);
|
||||
|
||||
/// Set the directory being watched (replaces any previous path).
|
||||
void setPath(const QString& path);
|
||||
|
||||
/// True while one or more Guards are alive.
|
||||
bool isSuspended() const;
|
||||
|
||||
/**
|
||||
* @brief RAII suspension guard. Nests safely; the only way to suspend
|
||||
* forwarding.
|
||||
*/
|
||||
class [[nodiscard]] Guard
|
||||
{
|
||||
public:
|
||||
explicit Guard(DirWatcherManager& manager);
|
||||
~Guard();
|
||||
Guard(const Guard&) = delete;
|
||||
Guard& operator=(const Guard&) = delete;
|
||||
Guard(Guard&&) = delete;
|
||||
Guard& operator=(Guard&&) = delete;
|
||||
|
||||
private:
|
||||
DirWatcherManager& m_manager;
|
||||
};
|
||||
|
||||
/// Returns a suspension Guard bound to the caller's scope.
|
||||
[[nodiscard]] Guard scopedGuard();
|
||||
|
||||
signals:
|
||||
/// Emitted when the watched directory changes and no Guard is active.
|
||||
void directoryChanged();
|
||||
|
||||
private slots:
|
||||
void onDirectoryChanged(const QString&);
|
||||
|
||||
private:
|
||||
QFileSystemWatcher m_watcher;
|
||||
int m_suspendDepth = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief manages downloading of files and provides progress information for gui
|
||||
*elements
|
||||
@@ -113,25 +61,6 @@ class DownloadManager : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief RAII full-reset guard. Use when the row count changes; drops
|
||||
* view selection/scroll state. Nests safely: inner guards coalesce into
|
||||
* the outermost scope so only one reset is emitted.
|
||||
*/
|
||||
class [[nodiscard]] ModelResetGuard
|
||||
{
|
||||
public:
|
||||
explicit ModelResetGuard(DownloadManager& manager);
|
||||
~ModelResetGuard();
|
||||
ModelResetGuard(const ModelResetGuard&) = delete;
|
||||
ModelResetGuard& operator=(const ModelResetGuard&) = delete;
|
||||
ModelResetGuard(ModelResetGuard&&) = delete;
|
||||
ModelResetGuard& operator=(ModelResetGuard&&) = delete;
|
||||
|
||||
private:
|
||||
DownloadManager& m_manager;
|
||||
};
|
||||
|
||||
enum DownloadState
|
||||
{
|
||||
STATE_STARTED = 0,
|
||||
@@ -262,6 +191,19 @@ public:
|
||||
**/
|
||||
void setOutputDirectory(const QString& outputDirectory, const bool refresh = true);
|
||||
|
||||
/**
|
||||
* @brief disables feedback from the downlods fileSystemWhatcher untill
|
||||
*disableDownloadsWatcherEnd() is called
|
||||
*
|
||||
**/
|
||||
static void startDisableDirWatcher();
|
||||
|
||||
/**
|
||||
* @brief re-enables feedback from the downlods fileSystemWhatcher after
|
||||
*disableDownloadsWatcherStart() was called
|
||||
**/
|
||||
static void endDisableDirWatcher();
|
||||
|
||||
/**
|
||||
* @return current download directory
|
||||
**/
|
||||
@@ -466,17 +408,8 @@ public:
|
||||
*/
|
||||
void queryDownloadListInfo();
|
||||
|
||||
/**
|
||||
* @return the directory watcher for the downloads folder; call
|
||||
* scopedGuard() on it to suspend across filesystem writes.
|
||||
*/
|
||||
DirWatcherManager& dirWatcher() { return m_DirWatcher; }
|
||||
|
||||
public: // IDownloadManager interface:
|
||||
int startDownloadURLs(const QStringList& urls);
|
||||
int startDownloadURLWithMeta(const QString& url, const QString& name,
|
||||
const QString& modName, const QString& version,
|
||||
const QString& source);
|
||||
int startDownloadNexusFile(const QString& gameName, int modID, int fileID);
|
||||
QString downloadPath(int id);
|
||||
|
||||
@@ -499,38 +432,16 @@ public: // IDownloadManager interface:
|
||||
|
||||
void pauseAll();
|
||||
|
||||
/**
|
||||
* @brief notify the UI that a single row's data changed. Preserves view
|
||||
* state; prefer over ModelResetGuard when the row count is unchanged.
|
||||
*
|
||||
* @param row the row that changed. This corresponds to the download index
|
||||
*/
|
||||
void notifyRowChanged(int row);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief emitted before the download list model is about to be reset
|
||||
*
|
||||
* Emitted by ModelResetGuard on construction. Views should call
|
||||
* beginResetModel() in response.
|
||||
*/
|
||||
void aboutToResetModel();
|
||||
void aboutToUpdate();
|
||||
|
||||
/**
|
||||
* @brief emitted after the download list model has been reset
|
||||
*
|
||||
* Emitted by ModelResetGuard on destruction. Views should call
|
||||
* endResetModel() in response.
|
||||
*/
|
||||
void modelReset();
|
||||
|
||||
/**
|
||||
* @brief signals that the specified download row's data has changed
|
||||
* @brief signals that the specified download has changed
|
||||
*
|
||||
* @param row the row that changed. This corresponds to the download index
|
||||
*/
|
||||
void rowChanged(int row);
|
||||
**/
|
||||
void update(int row);
|
||||
|
||||
/**
|
||||
* @brief signals the ui that a message should be displayed
|
||||
@@ -592,8 +503,6 @@ public slots:
|
||||
|
||||
void visitOnNexus(int index);
|
||||
|
||||
void visitUploaderProfile(int index);
|
||||
|
||||
void openFile(int index);
|
||||
|
||||
void openMetaFile(int index);
|
||||
@@ -627,6 +536,7 @@ private slots:
|
||||
void downloadFinished(int index = 0);
|
||||
void downloadError(QNetworkReply::NetworkError error);
|
||||
void metaDataChanged();
|
||||
void directoryChanged(const QString& dirctory);
|
||||
void checkDownloadTimeout();
|
||||
|
||||
private:
|
||||
@@ -666,6 +576,10 @@ private:
|
||||
|
||||
void removeFile(int index, bool deleteFile);
|
||||
|
||||
void refreshAlphabeticalTranslation();
|
||||
|
||||
bool ByName(int LHS, int RHS);
|
||||
|
||||
QString getFileNameFromNetworkReply(QNetworkReply* reply);
|
||||
|
||||
void setState(DownloadInfo* info, DownloadManager::DownloadState state);
|
||||
@@ -678,8 +592,6 @@ private:
|
||||
|
||||
void writeData(DownloadInfo* info);
|
||||
|
||||
QString getValidGameShortName(const QString& gameNexusName) const;
|
||||
|
||||
private:
|
||||
static const int AUTOMATIC_RETRIES = 3;
|
||||
|
||||
@@ -695,17 +607,22 @@ private:
|
||||
|
||||
QString m_OutputDirectory;
|
||||
std::set<int> m_RequestIDs;
|
||||
QVector<int> m_AlphabeticalTranslation;
|
||||
|
||||
DirWatcherManager m_DirWatcher;
|
||||
|
||||
// nesting depth of active ModelResetGuard scopes; see its docs
|
||||
int m_modelResetDepth = 0;
|
||||
QFileSystemWatcher m_DirWatcher;
|
||||
|
||||
SignalDownloadCallback m_DownloadComplete;
|
||||
SignalDownloadCallback m_DownloadPaused;
|
||||
SignalDownloadCallback m_DownloadFailed;
|
||||
SignalDownloadCallback m_DownloadRemoved;
|
||||
|
||||
// The dirWatcher is actually triggering off normal Mo operations such as deleting
|
||||
// downloads or editing .meta files so it needs to be disabled during operations that
|
||||
// are known to cause the creation or deletion of files in the Downloads folder.
|
||||
// Notably using QSettings to edit a file creates a temporarily .lock file that causes
|
||||
// the Watcher to trigger multiple listRefreshes freezing the ui.
|
||||
static int m_DirWatcherDisabler;
|
||||
|
||||
std::map<QString, int> m_DownloadFails;
|
||||
|
||||
bool m_ShowHidden;
|
||||
@@ -715,4 +632,14 @@ private:
|
||||
QTimer m_TimeoutTimer;
|
||||
};
|
||||
|
||||
class ScopedDisableDirWatcher
|
||||
{
|
||||
public:
|
||||
ScopedDisableDirWatcher(DownloadManager* downloadManager);
|
||||
~ScopedDisableDirWatcher();
|
||||
|
||||
private:
|
||||
DownloadManager* m_downloadManager;
|
||||
};
|
||||
|
||||
#endif // DOWNLOADMANAGER_H
|
||||
|
||||
@@ -37,8 +37,6 @@ DownloadsTab::DownloadsTab(OrganizerCore& core, Ui::MainWindow* mwui)
|
||||
SLOT(queryInfoMd5(int)));
|
||||
connect(ui.list, SIGNAL(visitOnNexus(int)), m_core.downloadManager(),
|
||||
SLOT(visitOnNexus(int)));
|
||||
connect(ui.list, SIGNAL(visitUploaderProfile(int)), m_core.downloadManager(),
|
||||
SLOT(visitUploaderProfile(int)));
|
||||
connect(ui.list, SIGNAL(openFile(int)), m_core.downloadManager(),
|
||||
SLOT(openFile(int)));
|
||||
connect(ui.list, SIGNAL(openMetaFile(int)), m_core.downloadManager(),
|
||||
|
||||
@@ -118,9 +118,6 @@ EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, int sel,
|
||||
connect(ui->useApplicationIcon, &QCheckBox::toggled, [&] {
|
||||
save();
|
||||
});
|
||||
connect(ui->minimizeToSystemTray, &QCheckBox::toggled, [&] {
|
||||
save();
|
||||
});
|
||||
connect(ui->hide, &QCheckBox::toggled, [&] {
|
||||
save();
|
||||
});
|
||||
@@ -139,7 +136,7 @@ int EditExecutablesDialog::exec()
|
||||
|
||||
void EditExecutablesDialog::loadCustomOverwrites()
|
||||
{
|
||||
const auto p = m_organizerCore.currentProfile();
|
||||
const auto* p = m_organizerCore.currentProfile();
|
||||
|
||||
for (const auto& e : m_executablesList) {
|
||||
const auto s = p->setting("custom_overwrites", e.title()).toString();
|
||||
@@ -152,7 +149,7 @@ void EditExecutablesDialog::loadCustomOverwrites()
|
||||
|
||||
void EditExecutablesDialog::loadForcedLibraries()
|
||||
{
|
||||
const auto p = m_organizerCore.currentProfile();
|
||||
const auto* p = m_organizerCore.currentProfile();
|
||||
|
||||
for (const auto& e : m_executablesList) {
|
||||
m_forcedLibraries.set(e.title(), p->forcedLibrariesEnabled(e.title()),
|
||||
@@ -237,7 +234,7 @@ bool EditExecutablesDialog::commitChanges()
|
||||
return false;
|
||||
}
|
||||
|
||||
auto profile = m_organizerCore.currentProfile();
|
||||
auto* profile = m_organizerCore.currentProfile();
|
||||
|
||||
// remove all the custom overwrites and forced libraries
|
||||
for (const auto& e : m_originalExecutables) {
|
||||
@@ -385,8 +382,6 @@ void EditExecutablesDialog::clearEdits()
|
||||
ui->configureLibraries->setEnabled(false);
|
||||
ui->useApplicationIcon->setEnabled(false);
|
||||
ui->useApplicationIcon->setChecked(false);
|
||||
ui->minimizeToSystemTray->setEnabled(false);
|
||||
ui->minimizeToSystemTray->setChecked(false);
|
||||
ui->hide->setEnabled(false);
|
||||
ui->hide->setChecked(false);
|
||||
|
||||
@@ -403,7 +398,6 @@ void EditExecutablesDialog::setEdits(const Executable& e)
|
||||
ui->steamAppID->setEnabled(!e.steamAppID().isEmpty());
|
||||
ui->steamAppID->setText(e.steamAppID());
|
||||
ui->useApplicationIcon->setChecked(e.usesOwnIcon());
|
||||
ui->minimizeToSystemTray->setChecked(e.minimizeToSystemTray());
|
||||
ui->hide->setChecked(e.hide());
|
||||
|
||||
m_lastGoodTitle = e.title();
|
||||
@@ -449,7 +443,6 @@ void EditExecutablesDialog::setEdits(const Executable& e)
|
||||
ui->useApplicationIcon->setEnabled(true);
|
||||
ui->createFilesInMod->setEnabled(true);
|
||||
ui->forceLoadLibraries->setEnabled(true);
|
||||
ui->minimizeToSystemTray->setEnabled(true);
|
||||
ui->hide->setEnabled(true);
|
||||
}
|
||||
|
||||
@@ -510,12 +503,6 @@ void EditExecutablesDialog::save()
|
||||
e->flags(e->flags() & (~Executable::UseApplicationIcon));
|
||||
}
|
||||
|
||||
if (ui->minimizeToSystemTray->isChecked()) {
|
||||
e->flags(e->flags() | Executable::MinimizeToSystemTray);
|
||||
} else {
|
||||
e->flags(e->flags() & (~Executable::MinimizeToSystemTray));
|
||||
}
|
||||
|
||||
if (ui->hide->isChecked()) {
|
||||
e->flags(e->flags() | Executable::Hide);
|
||||
} else {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user