mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
110
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4573d111a2 | ||
|
|
84ec954073 | ||
|
|
63188eb6f3 | ||
|
|
0a51fdf08e | ||
|
|
cb315b4179 | ||
|
|
d96d904765 | ||
|
|
9588667404 | ||
|
|
b008753e1d | ||
|
|
3c7ab3b668 | ||
|
|
d85019f4b1 | ||
|
|
05edcf8840 | ||
|
|
2a22461f14 | ||
|
|
0c3c822d77 | ||
|
|
f0ee9c3e4d | ||
|
|
83edfe0c96 | ||
|
|
86d833bcc8 | ||
|
|
58198a6bfd | ||
|
|
32339addbf | ||
|
|
dd875c05de | ||
|
|
17938b503a | ||
|
|
269d4f6765 | ||
|
|
0fa7f7469f | ||
|
|
ea1c2b46fe | ||
|
|
89f3c0d65a | ||
|
|
821f95b8ab | ||
|
|
716dbcc97d | ||
|
|
8e7ac4e064 | ||
|
|
69a8a40b99 | ||
|
|
229161565e | ||
|
|
9c3b390f08 | ||
|
|
5244544424 | ||
|
|
217ca284fe | ||
|
|
0aecc3427a | ||
|
|
b6627ff5e0 | ||
|
|
b0d86c9e01 | ||
|
|
a7d6eb75c2 | ||
|
|
6f09cf2205 | ||
|
|
e6abe486a7 | ||
|
|
52fcfaa292 | ||
|
|
4230313ef5 | ||
|
|
ff8057d34b | ||
|
|
b098214860 | ||
|
|
8cf429a1dd | ||
|
|
9f7bec01d0 | ||
|
|
643a50ad5a | ||
|
|
eaaa1b312d | ||
|
|
9c17ecc87e | ||
|
|
051589c38e | ||
|
|
48fae44566 | ||
|
|
e1c8d00979 | ||
|
|
0503097494 | ||
|
|
3a39f90870 | ||
|
|
18ad656586 | ||
|
|
eaafc489fc | ||
|
|
7799c348ba | ||
|
|
0a1f3efac5 | ||
|
|
1eea37e4e1 | ||
|
|
9a5965afa7 | ||
|
|
7853ba5f9a | ||
|
|
90dcc81715 | ||
|
|
1e75fd8dae | ||
|
|
61033814fd | ||
|
|
ca591dbd23 | ||
|
|
7602fef6e7 | ||
|
|
67b1f9dca2 | ||
|
|
5ae279d8bb | ||
|
|
81ef3d0a81 | ||
|
|
dc0e67a8b3 | ||
|
|
aa21a192cb | ||
|
|
d4d7ce1fd3 | ||
|
|
e31baf3ee6 | ||
|
|
5dcfca7c9d | ||
|
|
e9ee7e7f85 | ||
|
|
67d017fc98 | ||
|
|
a700e6a3ef | ||
|
|
c95de1b3aa | ||
|
|
351fc9ca9c | ||
|
|
53f0a2bc79 | ||
|
|
793dfb1637 | ||
|
|
d25a81071c | ||
|
|
ef9a61886c | ||
|
|
13a40b43c8 | ||
|
|
d7790cd717 | ||
|
|
84d632af6a | ||
|
|
b14b35349d | ||
|
|
83a4db2362 | ||
|
|
c797af8b76 | ||
|
|
ebf6ff3f76 | ||
|
|
02b5e73c2d | ||
|
|
b0b2f1d3a9 | ||
|
|
d8e406daa0 | ||
|
|
50dcc4c1d4 | ||
|
|
e21db0eaea | ||
|
|
859332e18d | ||
|
|
1fd8f44960 | ||
|
|
e0c655330d | ||
|
|
a0999cd42b | ||
|
|
eb47d4d0bb | ||
|
|
59476e38ec | ||
|
|
c5d36af06d | ||
|
|
8d1931bc6b | ||
|
|
c05be9f5c3 | ||
|
|
75714907d9 | ||
|
|
02471a3da1 | ||
|
|
afab0cec7e | ||
|
|
02cc97a58d | ||
|
|
ffd94e72b4 | ||
|
|
6435e1ab8a | ||
|
|
dbfa9b89d1 | ||
|
|
fe5c4255c8 |
+20
-4
@@ -83,7 +83,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string notr="true">Copyright 2011-2014 Sebastian Herbord</string>
|
||||
<string notr="true">Copyright 2011-2015 Sebastian Herbord</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -180,7 +180,18 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Ren (Korean)</string>
|
||||
<string notr="true">Ren (Korean)</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>... more (Can't track)</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -221,12 +232,12 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>GamerPoet</string>
|
||||
<string notr="true">GamerPoet</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Gopher</string>
|
||||
<string notr="true">Gopher</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
@@ -249,6 +260,11 @@
|
||||
<string notr="true">z929669</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string notr="true">thosrtanner</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
+27
-5
@@ -166,22 +166,32 @@ void CategoryFactory::saveCategories()
|
||||
unsigned int CategoryFactory::countCategories(std::tr1::function<bool (const Category &category)> filter)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
for (auto iter = m_Categories.begin(); iter != m_Categories.end(); ++iter) {
|
||||
if (filter(*iter)) {
|
||||
for (const Category &cat : m_Categories) {
|
||||
if (filter(cat)) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int CategoryFactory::addCategory(const QString &name, const std::vector<int> &nexusIDs, int parentID)
|
||||
{
|
||||
int id = 1;
|
||||
while (m_IDMap.find(id) != m_IDMap.end()) {
|
||||
++id;
|
||||
}
|
||||
addCategory(id, name, nexusIDs, parentID);
|
||||
|
||||
saveCategories();
|
||||
return id;
|
||||
}
|
||||
|
||||
void CategoryFactory::addCategory(int id, const QString &name, const std::vector<int> &nexusIDs, int parentID)
|
||||
{
|
||||
int index = m_Categories.size();
|
||||
m_Categories.push_back(Category(index, id, name, nexusIDs, parentID));
|
||||
for (std::vector<int>::const_iterator iter = nexusIDs.begin();
|
||||
iter != nexusIDs.end(); ++iter) {
|
||||
m_NexusMap[*iter] = index;
|
||||
for (int nexusID : nexusIDs) {
|
||||
m_NexusMap[nexusID] = index;
|
||||
}
|
||||
m_IDMap[id] = index;
|
||||
}
|
||||
@@ -305,6 +315,18 @@ int CategoryFactory::getCategoryIndex(int ID) const
|
||||
}
|
||||
|
||||
|
||||
int CategoryFactory::getCategoryID(const QString &name) const
|
||||
{
|
||||
auto iter = std::find_if(m_Categories.begin(), m_Categories.end(), [name] (const Category &cat) -> bool {
|
||||
return cat.m_Name == name;
|
||||
});
|
||||
if (iter != m_Categories.end()) {
|
||||
return iter->m_ID;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int CategoryFactory::resolveNexusID(int nexusID) const
|
||||
{
|
||||
|
||||
@@ -80,6 +80,8 @@ public:
|
||||
**/
|
||||
void saveCategories();
|
||||
|
||||
int addCategory(const QString &name, const std::vector<int> &nexusIDs, int parentID);
|
||||
|
||||
/**
|
||||
* @brief retrieve the number of available categories
|
||||
*
|
||||
@@ -142,6 +144,12 @@ public:
|
||||
**/
|
||||
int getCategoryID(unsigned int index) const;
|
||||
|
||||
/**
|
||||
* @brief look up the id of a category by its name
|
||||
* @note O(n)
|
||||
*/
|
||||
int getCategoryID(const QString &name) const;
|
||||
|
||||
/**
|
||||
* @brief look up the index of a category by its id
|
||||
*
|
||||
|
||||
@@ -76,11 +76,12 @@ void DirectoryRefresher::cleanStructure(DirectoryEntry *structure)
|
||||
}
|
||||
}
|
||||
|
||||
void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &archives)
|
||||
void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure, const QString &modName,
|
||||
int priority, const QString &directory, const QStringList &archives)
|
||||
{
|
||||
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
|
||||
|
||||
foreach (const QString &archive, archives) {
|
||||
for (const QString &archive : archives) {
|
||||
QFileInfo fileInfo(archive);
|
||||
if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) {
|
||||
try {
|
||||
@@ -93,23 +94,27 @@ void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure
|
||||
}
|
||||
}
|
||||
|
||||
void DirectoryRefresher::addModFilesToStructure(DirectoryEntry *directoryStructure, const QString &modName, int priority, const QString &directory, const QStringList &stealFiles)
|
||||
void DirectoryRefresher::addModFilesToStructure(DirectoryEntry *directoryStructure, const QString &modName,
|
||||
int priority, const QString &directory, const QStringList &stealFiles)
|
||||
{
|
||||
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
|
||||
|
||||
if (stealFiles.length() > 0) {
|
||||
// instead of adding all the files of the target directory, we just change the root of the specified
|
||||
// files to this mod
|
||||
FilesOrigin origin = directoryStructure->createOrigin(ToWString(modName), directoryW, priority);
|
||||
foreach (const QString &filename, stealFiles) {
|
||||
FilesOrigin &origin = directoryStructure->createOrigin(ToWString(modName), directoryW, priority);
|
||||
for (const QString &filename : stealFiles) {
|
||||
QFileInfo fileInfo(filename);
|
||||
FileEntry::Ptr file = directoryStructure->findFile(ToWString(fileInfo.fileName()));
|
||||
if (file.get() != nullptr) {
|
||||
if (file->getOrigin() == 0) {
|
||||
// replace data as the origin on this bsa
|
||||
file->removeOrigin(0);
|
||||
file->addOrigin(origin.getID(), file->getFileTime(), L"");
|
||||
}
|
||||
origin.addFile(file->getIndex());
|
||||
file->addOrigin(origin.getID(), file->getFileTime(), L"");
|
||||
} else {
|
||||
qWarning("%s not found", qPrintable(fileInfo.fileName()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -20,6 +20,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "downloadlistsortproxy.h"
|
||||
#include "downloadlist.h"
|
||||
#include "downloadmanager.h"
|
||||
#include "settings.h"
|
||||
|
||||
DownloadListSortProxy::DownloadListSortProxy(const DownloadManager *manager, QObject *parent)
|
||||
: QSortFilterProxyModel(parent), m_Manager(manager), m_CurrentFilter()
|
||||
@@ -55,12 +56,17 @@ bool DownloadListSortProxy::lessThan(const QModelIndex &left,
|
||||
}
|
||||
|
||||
|
||||
bool DownloadListSortProxy::filterAcceptsRow(int source_row, const QModelIndex&) const
|
||||
bool DownloadListSortProxy::filterAcceptsRow(int sourceRow, const QModelIndex&) const
|
||||
{
|
||||
if (m_CurrentFilter.length() == 0) {
|
||||
return true;
|
||||
} else if (source_row < m_Manager->numTotalDownloads()) {
|
||||
return sourceModel()->index(source_row, 0).data().toString().contains(m_CurrentFilter, Qt::CaseInsensitive);
|
||||
} else if (sourceRow < m_Manager->numTotalDownloads()) {
|
||||
int downloadIndex = sourceModel()->index(sourceRow, 0).data().toInt();
|
||||
|
||||
QString displayedName = Settings::instance().metaDownloads()
|
||||
? m_Manager->getDisplayName(downloadIndex)
|
||||
: m_Manager->getFileName(downloadIndex);
|
||||
return displayedName.contains(m_CurrentFilter, Qt::CaseInsensitive);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public slots:
|
||||
protected:
|
||||
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const;
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@ DownloadListWidgetCompactDelegate::DownloadListWidgetCompactDelegate(DownloadMan
|
||||
|
||||
m_DoneLabel->setVisible(false);
|
||||
|
||||
connect(manager, SIGNAL(stateChanged(int,DownloadManager::DownloadState)), this, SLOT(stateChanged(int,DownloadManager::DownloadState)));
|
||||
connect(manager, SIGNAL(stateChanged(int,DownloadManager::DownloadState)),
|
||||
this, SLOT(stateChanged(int,DownloadManager::DownloadState)));
|
||||
connect(manager, SIGNAL(downloadRemoved(int)), this, SLOT(resetCache(int)));
|
||||
}
|
||||
|
||||
@@ -116,24 +117,20 @@ void DownloadListWidgetCompactDelegate::paintRegularDownload(int downloadIndex)
|
||||
if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)) {
|
||||
m_DoneLabel->setVisible(true);
|
||||
m_Progress->setVisible(false);
|
||||
m_DoneLabel->setText(tr("Paused"));
|
||||
m_DoneLabel->setForegroundRole(QPalette::Link);
|
||||
m_DoneLabel->setText(QString("%1<img src=\":/MO/gui/inactive\">").arg(tr("Paused")));
|
||||
} else if (state == DownloadManager::STATE_FETCHINGMODINFO) {
|
||||
m_DoneLabel->setText(tr("Fetching Info 1"));
|
||||
m_DoneLabel->setText(QString("%1").arg(tr("Fetching Info 1")));
|
||||
} else if (state == DownloadManager::STATE_FETCHINGFILEINFO) {
|
||||
m_DoneLabel->setText(tr("Fetching Info 2"));
|
||||
m_DoneLabel->setText(QString("%1").arg(tr("Fetching Info 2")));
|
||||
} else if (state >= DownloadManager::STATE_READY) {
|
||||
m_DoneLabel->setVisible(true);
|
||||
m_Progress->setVisible(false);
|
||||
if (state == DownloadManager::STATE_INSTALLED) {
|
||||
m_DoneLabel->setText(tr("Installed"));
|
||||
m_DoneLabel->setForegroundRole(QPalette::Mid);
|
||||
m_DoneLabel->setText(QString("%1<img src=\":/MO/gui/check\">").arg(tr("Installed")));
|
||||
} else if (state == DownloadManager::STATE_UNINSTALLED) {
|
||||
m_DoneLabel->setText(tr("Uninstalled"));
|
||||
m_DoneLabel->setForegroundRole(QPalette::Dark);
|
||||
m_DoneLabel->setText(QString("%1<img src=\":/MO/gui/awaiting\">").arg(tr("Uninstalled")));
|
||||
} else {
|
||||
m_DoneLabel->setText(tr("Done"));
|
||||
m_DoneLabel->setForegroundRole(QPalette::WindowText);
|
||||
m_DoneLabel->setText(QString("%1<img src=\":/MO/gui/active\">").arg(tr("Done")));
|
||||
}
|
||||
if (m_Manager->isInfoIncomplete(downloadIndex)) {
|
||||
m_NameLabel->setText("<img src=\":/MO/gui/warning_16\"/> " + m_NameLabel->text());
|
||||
|
||||
@@ -1354,7 +1354,9 @@ void DownloadManager::downloadFinished()
|
||||
if (info->m_State == STATE_CANCELING) {
|
||||
setState(info, STATE_CANCELED);
|
||||
} else if (info->m_State == STATE_PAUSING) {
|
||||
info->m_Output.write(info->m_Reply->readAll());
|
||||
if (info->m_Output.isOpen()) {
|
||||
info->m_Output.write(info->m_Reply->readAll());
|
||||
}
|
||||
|
||||
if (error) {
|
||||
setState(info, STATE_ERROR);
|
||||
@@ -1426,7 +1428,10 @@ void DownloadManager::downloadFinished()
|
||||
void DownloadManager::downloadError(QNetworkReply::NetworkError error)
|
||||
{
|
||||
if (error != QNetworkReply::OperationCanceledError) {
|
||||
qWarning("Download error occured: %d", error);
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||
qWarning("%s (%d)", reply != nullptr ? qPrintable(reply->errorString())
|
||||
: "Download error occured",
|
||||
error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ private:
|
||||
|
||||
quint32 m_TaskProgressId;
|
||||
|
||||
MOBase::ModRepositoryFileInfo *m_FileInfo;
|
||||
MOBase::ModRepositoryFileInfo *m_FileInfo { nullptr };
|
||||
|
||||
bool m_Hidden;
|
||||
|
||||
|
||||
@@ -30,8 +30,10 @@ using namespace MOBase;
|
||||
using namespace MOShared;
|
||||
|
||||
EditExecutablesDialog::EditExecutablesDialog(const ExecutablesList &executablesList, QWidget *parent)
|
||||
: TutorableDialog("EditExecutables", parent),
|
||||
ui(new Ui::EditExecutablesDialog), m_CurrentItem(nullptr), m_ExecutablesList(executablesList)
|
||||
: TutorableDialog("EditExecutables", parent)
|
||||
, ui(new Ui::EditExecutablesDialog)
|
||||
, m_CurrentItem(nullptr)
|
||||
, m_ExecutablesList(executablesList)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@@ -47,7 +49,7 @@ ExecutablesList EditExecutablesDialog::getExecutablesList() const
|
||||
{
|
||||
ExecutablesList newList;
|
||||
for (int i = 0; i < ui->executablesListBox->count(); ++i) {
|
||||
newList.addExecutable(ui->executablesListBox->item(i)->data(Qt::UserRole).value<Executable>());
|
||||
newList.addExecutable(m_ExecutablesList.find(ui->executablesListBox->item(i)->text()));
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
@@ -60,10 +62,7 @@ void EditExecutablesDialog::refreshExecutablesWidget()
|
||||
|
||||
for(; current != end; ++current) {
|
||||
QListWidgetItem *newItem = new QListWidgetItem(current->m_Title);
|
||||
QVariant temp;
|
||||
temp.setValue(*current);
|
||||
newItem->setData(Qt::UserRole, temp);
|
||||
newItem->setTextColor(current->m_Custom ? QColor(Qt::black) : QColor(Qt::darkGray));
|
||||
newItem->setTextColor(current->isCustom() ? QColor(Qt::black) : QColor(Qt::darkGray));
|
||||
ui->executablesListBox->addItem(newItem);
|
||||
}
|
||||
|
||||
@@ -72,9 +71,9 @@ void EditExecutablesDialog::refreshExecutablesWidget()
|
||||
}
|
||||
|
||||
|
||||
void EditExecutablesDialog::on_binaryEdit_textChanged(const QString &arg1)
|
||||
void EditExecutablesDialog::on_binaryEdit_textChanged(const QString &name)
|
||||
{
|
||||
QFileInfo fileInfo(arg1);
|
||||
QFileInfo fileInfo(name);
|
||||
ui->addButton->setEnabled(fileInfo.exists() && fileInfo.isFile());
|
||||
}
|
||||
|
||||
@@ -87,19 +86,27 @@ void EditExecutablesDialog::resetInput()
|
||||
ui->appIDOverwriteEdit->clear();
|
||||
ui->overwriteAppIDBox->setChecked(false);
|
||||
ui->closeCheckBox->setChecked(false);
|
||||
ui->useAppIconCheckBox->setChecked(false);
|
||||
m_CurrentItem = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void EditExecutablesDialog::saveExecutable()
|
||||
{
|
||||
m_ExecutablesList.addExecutable(ui->titleEdit->text(), QDir::fromNativeSeparators(ui->binaryEdit->text()),
|
||||
ui->argumentsEdit->text(), QDir::fromNativeSeparators(ui->workingDirEdit->text()),
|
||||
(ui->closeCheckBox->checkState() == Qt::Checked) ? ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE
|
||||
: ExecutableInfo::CloseMOStyle::DEFAULT_STAY,
|
||||
ui->overwriteAppIDBox->isChecked() ? ui->appIDOverwriteEdit->text() : "",
|
||||
true, false);
|
||||
}
|
||||
m_ExecutablesList.updateExecutable(ui->titleEdit->text(),
|
||||
QDir::fromNativeSeparators(ui->binaryEdit->text()),
|
||||
ui->argumentsEdit->text(),
|
||||
QDir::fromNativeSeparators(ui->workingDirEdit->text()),
|
||||
(ui->closeCheckBox->checkState() == Qt::Checked) ?
|
||||
ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE
|
||||
: ExecutableInfo::CloseMOStyle::DEFAULT_STAY,
|
||||
ui->overwriteAppIDBox->isChecked() ?
|
||||
ui->appIDOverwriteEdit->text() : "",
|
||||
Executable::UseApplicationIcon | Executable::CustomExecutable,
|
||||
(ui->useAppIconCheckBox->isChecked() ?
|
||||
Executable::UseApplicationIcon : Executable::Flags())
|
||||
| Executable::CustomExecutable);
|
||||
}
|
||||
|
||||
|
||||
void EditExecutablesDialog::delayedRefresh()
|
||||
@@ -113,7 +120,9 @@ void EditExecutablesDialog::delayedRefresh()
|
||||
|
||||
void EditExecutablesDialog::on_addButton_clicked()
|
||||
{
|
||||
saveExecutable();
|
||||
if (executableChanged()) {
|
||||
saveExecutable();
|
||||
}
|
||||
|
||||
resetInput();
|
||||
refreshExecutablesWidget();
|
||||
@@ -170,8 +179,6 @@ void EditExecutablesDialog::on_browseDirButton_clicked()
|
||||
|
||||
void EditExecutablesDialog::on_removeButton_clicked()
|
||||
{
|
||||
// QLineEdit *binaryEdit = findChild<QLineEdit*>("binaryEdit");
|
||||
|
||||
if (QMessageBox::question(this, tr("Confirm"), tr("Really remove \"%1\" from executables?").arg(ui->titleEdit->text()),
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
m_ExecutablesList.remove(ui->titleEdit->text());
|
||||
@@ -206,15 +213,19 @@ void EditExecutablesDialog::on_titleEdit_textChanged(const QString &arg1)
|
||||
bool EditExecutablesDialog::executableChanged()
|
||||
{
|
||||
if (m_CurrentItem != nullptr) {
|
||||
const Executable &selectedExecutable = m_CurrentItem->data(Qt::UserRole).value<Executable>();
|
||||
|
||||
Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text()));
|
||||
return selectedExecutable.m_Arguments != ui->argumentsEdit->text()
|
||||
|| selectedExecutable.m_SteamAppID != ui->appIDOverwriteEdit->text()
|
||||
|| selectedExecutable.m_WorkingDirectory != QDir::fromNativeSeparators(ui->workingDirEdit->text())
|
||||
|| selectedExecutable.m_BinaryInfo.absoluteFilePath() != QDir::fromNativeSeparators(ui->binaryEdit->text())
|
||||
|| (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE) != ui->closeCheckBox->isChecked();
|
||||
|| (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE) != ui->closeCheckBox->isChecked()
|
||||
|| selectedExecutable.usesOwnIcon() != ui->useAppIconCheckBox->isChecked();
|
||||
} else {
|
||||
return false;
|
||||
QFileInfo fileInfo(ui->binaryEdit->text());
|
||||
return !ui->binaryEdit->text().isEmpty()
|
||||
&& !ui->titleEdit->text().isEmpty()
|
||||
&& fileInfo.exists()
|
||||
&& fileInfo.isFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +283,7 @@ void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &cur
|
||||
|
||||
m_CurrentItem = ui->executablesListBox->item(current.row());
|
||||
|
||||
const Executable &selectedExecutable = m_CurrentItem->data(Qt::UserRole).value<Executable>();
|
||||
Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text()));
|
||||
|
||||
ui->titleEdit->setText(selectedExecutable.m_Title);
|
||||
ui->binaryEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath()));
|
||||
@@ -286,12 +297,13 @@ void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &cur
|
||||
ui->closeCheckBox->setEnabled(true);
|
||||
ui->closeCheckBox->setToolTip(tr("If checked, MO will be closed once the specified executable is run."));
|
||||
}
|
||||
ui->removeButton->setEnabled(selectedExecutable.m_Custom);
|
||||
ui->removeButton->setEnabled(selectedExecutable.isCustom());
|
||||
ui->overwriteAppIDBox->setChecked(!selectedExecutable.m_SteamAppID.isEmpty());
|
||||
if (!selectedExecutable.m_SteamAppID.isEmpty()) {
|
||||
ui->appIDOverwriteEdit->setText(selectedExecutable.m_SteamAppID);
|
||||
} else {
|
||||
ui->appIDOverwriteEdit->clear();
|
||||
}
|
||||
ui->useAppIconCheckBox->setChecked(selectedExecutable.usesOwnIcon());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>384</width>
|
||||
<height>362</height>
|
||||
<height>446</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -26,7 +26,7 @@
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
<enum>Qt::TargetMoveAction</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
@@ -164,21 +164,28 @@ Right now the only case I know of where this needs to be overwritten is for the
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="closeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>If checked, MO will be closed once the specified executable is run.</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>If checked, MO will be closed once the specified executable is run.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close MO when started</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useAppIconCheckBox">
|
||||
<property name="text">
|
||||
<string>Use Application's Icon for shortcuts</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="closeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>If checked, MO will be closed once the specified executable is run.</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>If checked, MO will be closed once the specified executable is run.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close MO when started</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addButton">
|
||||
<property name="toolTip">
|
||||
@@ -240,6 +247,10 @@ Right now the only case I know of where this needs to be overwritten is for the
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>executablesListBox</zorder>
|
||||
<zorder>closeButton</zorder>
|
||||
<zorder>closeCheckBox</zorder>
|
||||
<zorder>useAppIconCheckBox</zorder>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
+37
-74
@@ -30,39 +30,6 @@ using namespace MOBase;
|
||||
using namespace MOShared;
|
||||
|
||||
|
||||
static QDataStream &operator<<(QDataStream &out, const Executable &obj)
|
||||
{
|
||||
out << obj.m_Title
|
||||
<< obj.m_BinaryInfo.absoluteFilePath()
|
||||
<< obj.m_Arguments
|
||||
<< static_cast<std::underlying_type<ExecutableInfo::CloseMOStyle>::type>(obj.m_CloseMO)
|
||||
<< obj.m_SteamAppID
|
||||
<< obj.m_WorkingDirectory
|
||||
<< obj.m_Custom
|
||||
<< obj.m_Toolbar;
|
||||
return out;
|
||||
}
|
||||
|
||||
static QDataStream &operator>>(QDataStream &in, Executable &obj)
|
||||
{
|
||||
QString binaryTemp;
|
||||
int closeStyleTemp;
|
||||
in >> obj.m_Title >> binaryTemp >> obj.m_Arguments >> closeStyleTemp
|
||||
>> obj.m_SteamAppID >> obj.m_WorkingDirectory >> obj.m_Custom >> obj.m_Toolbar;
|
||||
|
||||
obj.m_CloseMO = static_cast<ExecutableInfo::CloseMOStyle>(closeStyleTemp);
|
||||
obj.m_BinaryInfo.setFile(binaryTemp);
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
void registerExecutable()
|
||||
{
|
||||
qRegisterMetaType<Executable>("Executable");
|
||||
qRegisterMetaTypeStreamOperators<Executable>("Executable");
|
||||
}
|
||||
|
||||
|
||||
ExecutablesList::ExecutablesList()
|
||||
{
|
||||
}
|
||||
@@ -102,23 +69,23 @@ void ExecutablesList::getExecutables(std::vector<Executable>::const_iterator &be
|
||||
|
||||
const Executable &ExecutablesList::find(const QString &title) const
|
||||
{
|
||||
for (std::vector<Executable>::const_iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) {
|
||||
if (iter->m_Title == title) {
|
||||
return *iter;
|
||||
for (Executable const &exe : m_Executables) {
|
||||
if (exe.m_Title == title) {
|
||||
return exe;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("invalid name");
|
||||
throw std::runtime_error(QString("invalid name %1").arg(title).toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
|
||||
Executable &ExecutablesList::find(const QString &title)
|
||||
{
|
||||
for (Executable &exe : m_Executables) {
|
||||
if (QString::compare(exe.m_Title, title, Qt::CaseInsensitive) == 0) {
|
||||
if (exe.m_Title == title) {
|
||||
return exe;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("invalid name");
|
||||
throw std::runtime_error(QString("invalid name %1").arg(title).toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
|
||||
@@ -162,42 +129,34 @@ void ExecutablesList::addExecutable(const Executable &executable)
|
||||
}
|
||||
|
||||
|
||||
void ExecutablesList::position(const QString &title, bool toolbar, int pos)
|
||||
{
|
||||
auto existingExe = findExe(title);
|
||||
if (existingExe != m_Executables.end()) {
|
||||
Executable temp = *existingExe;
|
||||
temp.m_Toolbar = toolbar;
|
||||
m_Executables.erase(existingExe);
|
||||
m_Executables.insert(m_Executables.begin() + pos, temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ExecutablesList::addExecutable(const QString &title, const QString &executableName, const QString &arguments,
|
||||
const QString &workingDirectory, ExecutableInfo::CloseMOStyle closeMO, const QString &steamAppID,
|
||||
bool custom, bool toolbar, int pos)
|
||||
void ExecutablesList::updateExecutable(const QString &title,
|
||||
const QString &executableName,
|
||||
const QString &arguments,
|
||||
const QString &workingDirectory,
|
||||
ExecutableInfo::CloseMOStyle closeMO,
|
||||
const QString &steamAppID,
|
||||
Executable::Flags mask,
|
||||
Executable::Flags flags)
|
||||
{
|
||||
QFileInfo file(executableName);
|
||||
auto existingExe = findExe(title);
|
||||
flags &= mask;
|
||||
|
||||
if (existingExe != m_Executables.end()) {
|
||||
existingExe->m_Title = title;
|
||||
existingExe->m_Custom = custom;
|
||||
existingExe->m_CloseMO = closeMO;
|
||||
existingExe->m_Toolbar = toolbar;
|
||||
if (custom) {
|
||||
// for pre-configured executables don't overwrite settings we didn't store
|
||||
existingExe->m_BinaryInfo = file;
|
||||
existingExe->m_Flags &= ~mask;
|
||||
existingExe->m_Flags |= flags;
|
||||
// for pre-configured executables don't overwrite settings we didn't store
|
||||
if (flags & Executable::CustomExecutable) {
|
||||
if (file.exists()) {
|
||||
// don't overwrite a valid binary with an invalid one
|
||||
existingExe->m_BinaryInfo = file;
|
||||
}
|
||||
existingExe->m_Arguments = arguments;
|
||||
existingExe->m_WorkingDirectory = workingDirectory;
|
||||
existingExe->m_SteamAppID = steamAppID;
|
||||
}
|
||||
if (pos >= 0) {
|
||||
Executable temp = *existingExe;
|
||||
m_Executables.erase(existingExe);
|
||||
m_Executables.insert(m_Executables.begin() + pos, temp);
|
||||
}
|
||||
} else {
|
||||
Executable newExe;
|
||||
newExe.m_Title = title;
|
||||
@@ -206,13 +165,8 @@ void ExecutablesList::addExecutable(const QString &title, const QString &executa
|
||||
newExe.m_Arguments = arguments;
|
||||
newExe.m_WorkingDirectory = workingDirectory;
|
||||
newExe.m_SteamAppID = steamAppID;
|
||||
newExe.m_Custom = true;
|
||||
newExe.m_Toolbar = toolbar;
|
||||
if ((pos < 0) || (pos >= static_cast<int>(m_Executables.size()))) {
|
||||
m_Executables.push_back(newExe);
|
||||
} else {
|
||||
m_Executables.insert(m_Executables.begin() + pos, newExe);
|
||||
}
|
||||
newExe.m_Flags = Executable::CustomExecutable | flags;
|
||||
m_Executables.push_back(newExe);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +174,7 @@ void ExecutablesList::addExecutable(const QString &title, const QString &executa
|
||||
void ExecutablesList::remove(const QString &title)
|
||||
{
|
||||
for (std::vector<Executable>::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) {
|
||||
if (iter->m_Custom && (iter->m_Title == title)) {
|
||||
if (iter->isCustom() && (iter->m_Title == title)) {
|
||||
m_Executables.erase(iter);
|
||||
break;
|
||||
}
|
||||
@@ -241,8 +195,17 @@ void ExecutablesList::addExecutableInternal(const QString &title, const QString
|
||||
newExe.m_Arguments = arguments;
|
||||
newExe.m_WorkingDirectory = workingDirectory;
|
||||
newExe.m_SteamAppID = steamAppID;
|
||||
newExe.m_Custom = false;
|
||||
newExe.m_Toolbar = false;
|
||||
newExe.m_Flags = 0;
|
||||
m_Executables.push_back(newExe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Executable::showOnToolbar(bool state)
|
||||
{
|
||||
if (state) {
|
||||
m_Flags |= ShowInToolbar;
|
||||
} else {
|
||||
m_Flags &= ~ShowInToolbar;
|
||||
}
|
||||
}
|
||||
|
||||
+59
-30
@@ -39,13 +39,26 @@ struct Executable {
|
||||
QString m_SteamAppID;
|
||||
QString m_WorkingDirectory;
|
||||
|
||||
bool m_Custom;
|
||||
bool m_Toolbar;
|
||||
enum Flag {
|
||||
CustomExecutable = 0x01,
|
||||
ShowInToolbar = 0x02,
|
||||
UseApplicationIcon = 0x04,
|
||||
|
||||
AllFlags = 0xff //I know, I know
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
|
||||
Flags m_Flags;
|
||||
|
||||
bool isCustom() const { return m_Flags.testFlag(CustomExecutable); }
|
||||
|
||||
bool isShownOnToolbar() const { return m_Flags.testFlag(ShowInToolbar); }
|
||||
|
||||
void showOnToolbar(bool state);
|
||||
|
||||
bool usesOwnIcon() const { return m_Flags.testFlag(UseApplicationIcon); }
|
||||
};
|
||||
Q_DECLARE_METATYPE(Executable)
|
||||
|
||||
|
||||
void registerExecutable();
|
||||
|
||||
|
||||
/*!
|
||||
@@ -68,13 +81,13 @@ public:
|
||||
void init(MOBase::IPluginGame *game);
|
||||
|
||||
/**
|
||||
* @brief retrieve an executable by index
|
||||
* @brief find an executable by its name
|
||||
*
|
||||
* @param index index of the executable to look up
|
||||
* @return reference to the executable
|
||||
* @exception out_of_range will throw an exception if the index is invalid
|
||||
* @param title the title of the executable to look up
|
||||
* @return the executable
|
||||
* @exception runtime_error will throw an exception if the name is not correct
|
||||
**/
|
||||
const Executable &get(int index) const { return m_Executables.at(index); }
|
||||
const Executable &find(const QString &title) const;
|
||||
|
||||
/**
|
||||
* @brief find an executable by its name
|
||||
@@ -83,16 +96,7 @@ public:
|
||||
* @return the executable
|
||||
* @exception runtime_error will throw an exception if the name is not correct
|
||||
**/
|
||||
const Executable &find(const QString &tilte) const;
|
||||
|
||||
/**
|
||||
* @brief find an executable by its name
|
||||
*
|
||||
* @param title the title of the executable to look up
|
||||
* @return the executable
|
||||
* @exception runtime_error will throw an exception if the name is not correct
|
||||
**/
|
||||
Executable &find(const QString &tilte);
|
||||
Executable &find(const QString &title);
|
||||
|
||||
/**
|
||||
* @brief find an executable by a fileinfo structure
|
||||
@@ -123,17 +127,33 @@ public:
|
||||
* @param arguments arguments to pass to the executable
|
||||
* @param closeMO if true, MO will be closed when the binary is started
|
||||
**/
|
||||
void addExecutable(const QString &title, const QString &executableName, const QString &arguments,
|
||||
const QString &workingDirectory, MOBase::ExecutableInfo::CloseMOStyle closeMO, const QString &steamAppID,
|
||||
bool custom, bool toolbar, int pos = -1);
|
||||
void addExecutable(const QString &title,
|
||||
const QString &executableName,
|
||||
const QString &arguments,
|
||||
const QString &workingDirectory,
|
||||
MOBase::ExecutableInfo::CloseMOStyle closeMO,
|
||||
const QString &steamAppID,
|
||||
Executable::Flags flags)
|
||||
{
|
||||
updateExecutable(title, executableName, arguments, workingDirectory, closeMO, steamAppID, Executable::AllFlags, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief change position of an executable which is expected to exist
|
||||
* @param title title of the executable
|
||||
* @param toolbar enable/disable placement on the toolbar
|
||||
* @param pos new position for the executable
|
||||
*/
|
||||
void position(const QString &title, bool toolbar, int pos);
|
||||
* @brief Update an executable to the list
|
||||
*
|
||||
* @param title name displayed in the UI
|
||||
* @param executableName the actual filename to execute
|
||||
* @param arguments arguments to pass to the executable
|
||||
* @param closeMO if true, MO will be closed when the binary is started
|
||||
**/
|
||||
void updateExecutable(const QString &title,
|
||||
const QString &executableName,
|
||||
const QString &arguments,
|
||||
const QString &workingDirectory,
|
||||
MOBase::ExecutableInfo::CloseMOStyle closeMO,
|
||||
const QString &steamAppID,
|
||||
Executable::Flags mask,
|
||||
Executable::Flags flags);
|
||||
|
||||
/**
|
||||
* @brief remove the executable with the specified file name. This needs to be an absolute file path
|
||||
@@ -159,6 +179,13 @@ public:
|
||||
**/
|
||||
void getExecutables(std::vector<Executable>::iterator &begin, std::vector<Executable>::iterator &end);
|
||||
|
||||
/**
|
||||
* @brief get the number of executables (custom or otherwise)
|
||||
**/
|
||||
size_t size() const {
|
||||
return m_Executables.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<Executable>::iterator findExe(const QString &title);
|
||||
@@ -173,4 +200,6 @@ private:
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Executable::Flags)
|
||||
|
||||
#endif // EXECUTABLESLIST_H
|
||||
|
||||
+38
-43
@@ -114,22 +114,26 @@ void InstallationManager::queryPassword(LPSTR password)
|
||||
void InstallationManager::mapToArchive(const DirectoryTree::Node *node, std::wstring path, FileData * const *data)
|
||||
{
|
||||
if (path.length() > 0) {
|
||||
path.append(L"\\");
|
||||
// when using a long windows path (starting with \\?\) we apparently can have redundant
|
||||
// . components in the path. This wasn't a problem with "regular" path names.
|
||||
if (path == L".") {
|
||||
path.clear();
|
||||
} else {
|
||||
path.append(L"\\");
|
||||
}
|
||||
}
|
||||
|
||||
for (DirectoryTree::const_leaf_iterator iter = node->leafsBegin(); iter != node->leafsEnd(); ++iter) {
|
||||
data[iter->getIndex()]->setSkip(false);
|
||||
std::wstring temp = path.substr().append(ToWString(iter->getName()));
|
||||
data[iter->getIndex()]->setOutputFileName(temp.c_str());
|
||||
std::wstring temp = path + iter->getName().toStdWString();
|
||||
data[iter->getIndex()]->addOutputFileName(temp.c_str());
|
||||
}
|
||||
|
||||
for (DirectoryTree::const_node_iterator iter = node->nodesBegin(); iter != node->nodesEnd(); ++iter) {
|
||||
std::wstring temp = path + (*iter)->getData().name.toStdWString();
|
||||
if ((*iter)->getData().index != -1) {
|
||||
data[(*iter)->getData().index]->setSkip(false);
|
||||
std::wstring temp = path.substr().append(ToWString((*iter)->getData().name));
|
||||
data[(*iter)->getData().index]->setOutputFileName(temp.c_str());
|
||||
data[(*iter)->getData().index]->addOutputFileName(temp.c_str());
|
||||
}
|
||||
mapToArchive(*iter, path.substr().append(ToWString((*iter)->getData().name)), data);
|
||||
mapToArchive(*iter, temp, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,11 +144,6 @@ void InstallationManager::mapToArchive(const DirectoryTree::Node *baseNode)
|
||||
size_t size;
|
||||
m_CurrentArchive->getFileList(data, size);
|
||||
|
||||
// first disable all files + folders, we will re-enable those present in baseNode
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
data[i]->setSkip(true);
|
||||
}
|
||||
|
||||
std::wstring currentPath;
|
||||
|
||||
mapToArchive(baseNode, currentPath, data);
|
||||
@@ -163,32 +162,29 @@ bool InstallationManager::unpackSingleFile(const QString &fileName)
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (_wcsicmp(data[i]->getFileName(), ToWString(fileName).c_str()) == 0) {
|
||||
available = true;
|
||||
data[i]->setSkip(false);
|
||||
data[i]->setOutputFileName(ToWString(baseName).c_str());
|
||||
data[i]->addOutputFileName(ToWString(baseName).c_str());
|
||||
m_TempFilesToDelete.insert(baseName);
|
||||
} else {
|
||||
data[i]->setSkip(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (available) {
|
||||
m_InstallationProgress.setWindowTitle(tr("Extracting files"));
|
||||
m_InstallationProgress.setLabelText(QString());
|
||||
m_InstallationProgress.setValue(0);
|
||||
m_InstallationProgress.setWindowModality(Qt::WindowModal);
|
||||
m_InstallationProgress.show();
|
||||
|
||||
bool res = m_CurrentArchive->extract(ToWString(QDir::toNativeSeparators(QDir::tempPath())).c_str(),
|
||||
new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
|
||||
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::dummyProgressFile),
|
||||
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::report7ZipError));
|
||||
|
||||
m_InstallationProgress.hide();
|
||||
|
||||
return res;
|
||||
} else {
|
||||
if (!available) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_InstallationProgress.setWindowTitle(tr("Extracting files"));
|
||||
m_InstallationProgress.setLabelText(QString());
|
||||
m_InstallationProgress.setValue(0);
|
||||
m_InstallationProgress.setWindowModality(Qt::WindowModal);
|
||||
m_InstallationProgress.show();
|
||||
|
||||
bool res = m_CurrentArchive->extract(ToWString(QDir::toNativeSeparators(QDir::tempPath())).c_str(),
|
||||
new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
|
||||
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::dummyProgressFile),
|
||||
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::report7ZipError));
|
||||
|
||||
m_InstallationProgress.hide();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -245,14 +241,11 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool
|
||||
++targetFile;
|
||||
}
|
||||
}
|
||||
data[i]->setOutputFileName(targetFile);
|
||||
data[i]->addOutputFileName(targetFile);
|
||||
|
||||
result.append(QDir::tempPath().append("/").append(ToQString(targetFile)));
|
||||
|
||||
data[i]->setSkip(false);
|
||||
m_TempFilesToDelete.insert(ToQString(targetFile));
|
||||
} else {
|
||||
data[i]->setSkip(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,8 +528,8 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
|
||||
return false;
|
||||
}
|
||||
|
||||
QString targetDirectoryNative = m_ModsDirectory + "\\" + modName;
|
||||
QString targetDirectory = QDir::fromNativeSeparators(targetDirectoryNative);
|
||||
QString targetDirectory = QDir(m_ModsDirectory + "/" + modName).canonicalPath();
|
||||
QString targetDirectoryNative = QDir::toNativeSeparators(targetDirectory);
|
||||
|
||||
qDebug("installing to \"%s\"", targetDirectoryNative.toUtf8().constData());
|
||||
|
||||
@@ -545,7 +538,7 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
|
||||
m_InstallationProgress.setValue(0);
|
||||
m_InstallationProgress.setWindowModality(Qt::WindowModal);
|
||||
m_InstallationProgress.show();
|
||||
if (!m_CurrentArchive->extract(ToWString("\\\\?\\" + QDir::toNativeSeparators(targetDirectory)).c_str(),
|
||||
if (!m_CurrentArchive->extract(ToWString("\\\\?\\" + targetDirectoryNative).c_str(),
|
||||
new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
|
||||
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::updateProgressFile),
|
||||
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::report7ZipError))) {
|
||||
@@ -598,7 +591,7 @@ bool InstallationManager::wasCancelled()
|
||||
}
|
||||
|
||||
|
||||
void InstallationManager::postInstallCleanup() const
|
||||
void InstallationManager::postInstallCleanup()
|
||||
{
|
||||
m_CurrentArchive->close();
|
||||
|
||||
@@ -612,12 +605,14 @@ void InstallationManager::postInstallCleanup() const
|
||||
|
||||
// clean up temp files
|
||||
// TODO: this doesn't yet remove directories. Also, the files may be left there if this point isn't reached
|
||||
foreach (const QString &tempFile, m_TempFilesToDelete) {
|
||||
for (const QString &tempFile : m_TempFilesToDelete) {
|
||||
QFileInfo fileInfo(QDir::tempPath() + "/" + tempFile);
|
||||
QFile::remove(fileInfo.absoluteFilePath());
|
||||
directoriesToRemove.insert(fileInfo.absolutePath());
|
||||
}
|
||||
|
||||
m_TempFilesToDelete.clear();
|
||||
|
||||
// try to delete each directory we had temporary files in. the call fails for non-empty directories which is ok
|
||||
foreach (const QString &dir, directoriesToRemove) {
|
||||
QDir().rmdir(dir);
|
||||
@@ -629,7 +624,7 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
|
||||
{
|
||||
QFileInfo fileInfo(fileName);
|
||||
if (m_SupportedExtensions.find(fileInfo.suffix()) == m_SupportedExtensions.end()) {
|
||||
reportError(tr("File format \"%1\" not supported").arg(fileInfo.completeSuffix()));
|
||||
reportError(tr("File format \"%1\" not supported").arg(fileInfo.suffix()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ private:
|
||||
|
||||
bool ensureValidModName(MOBase::GuessedValue<QString> &name) const;
|
||||
|
||||
void postInstallCleanup() const;
|
||||
void postInstallCleanup();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ char LogBuffer::msgTypeID(QtMsgType type)
|
||||
void LogBuffer::log(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
// QMutexLocker doesn't support timeout...
|
||||
if (!s_Mutex.tryLock(50)) {
|
||||
if (!s_Mutex.tryLock(100)) {
|
||||
fprintf(stderr, "failed to log: %s", qPrintable(message));
|
||||
return;
|
||||
}
|
||||
|
||||
+58
-45
@@ -62,6 +62,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "selectiondialog.h"
|
||||
#include "moapplication.h"
|
||||
#include "tutorialmanager.h"
|
||||
#include "nxmaccessmanager.h"
|
||||
#include <iostream>
|
||||
#include <QMessageBox>
|
||||
#include <QSharedMemory>
|
||||
@@ -172,9 +173,12 @@ void cleanupDir()
|
||||
|
||||
for (const QString &fileName : fileNames) {
|
||||
QString fullPath = qApp->applicationDirPath() + "/" + fileName;
|
||||
if (QFile::exists(fullPath)
|
||||
&& !shellDelete(QStringList(fullPath), true)) {
|
||||
qDebug("failed to remove obsolete %s", qPrintable(fullPath));
|
||||
if (QFile::exists(fullPath)) {
|
||||
if (shellDelete(QStringList(fullPath), true)) {
|
||||
qDebug("removed obsolete file %s", qPrintable(fullPath));
|
||||
} else {
|
||||
qDebug("failed to remove obsolete %s", qPrintable(fullPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,22 +207,28 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except
|
||||
FuncMiniDumpWriteDump funcDump = (FuncMiniDumpWriteDump)::GetProcAddress(dbgDLL, "MiniDumpWriteDump");
|
||||
if (funcDump) {
|
||||
if (QMessageBox::question(nullptr, QObject::tr("Woops"),
|
||||
QObject::tr("ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file "
|
||||
"(%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. "
|
||||
"Please include a short description of what you were doing when the crash happened").arg(qApp->applicationFilePath().append(".dmp")),
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
QObject::tr("ModOrganizer has crashed! "
|
||||
"Should a diagnostic file be created? "
|
||||
"If you send me this file (%1) to sherb@gmx.net, "
|
||||
"the bug is a lot more likely to be fixed. "
|
||||
"Please include a short description of what you were "
|
||||
"doing when the crash happened"
|
||||
).arg(qApp->applicationFilePath().append(".dmp")),
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
|
||||
std::wstring dumpName = ToWString(qApp->applicationFilePath().append(".dmp"));
|
||||
|
||||
HANDLE dumpFile = ::CreateFile(dumpName.c_str(),
|
||||
GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
GENERIC_WRITE, FILE_SHARE_WRITE, nullptr,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (dumpFile != INVALID_HANDLE_VALUE) {
|
||||
_MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
|
||||
exceptionInfo.ThreadId = ::GetCurrentThreadId();
|
||||
exceptionInfo.ExceptionPointers = exceptionPtrs;
|
||||
exceptionInfo.ClientPointers = false;
|
||||
|
||||
BOOL success = funcDump(::GetCurrentProcess(), ::GetCurrentProcessId(), dumpFile, MiniDumpNormal, &exceptionInfo, nullptr, nullptr);
|
||||
BOOL success = funcDump(::GetCurrentProcess(), ::GetCurrentProcessId(), dumpFile,
|
||||
MiniDumpNormal, &exceptionInfo, nullptr, nullptr);
|
||||
|
||||
::FlushFileBuffers(dumpFile);
|
||||
::CloseHandle(dumpFile);
|
||||
@@ -246,11 +256,6 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except
|
||||
return result;
|
||||
}
|
||||
|
||||
static void registerMetaTypes()
|
||||
{
|
||||
registerExecutable();
|
||||
}
|
||||
|
||||
static bool HaveWriteAccess(const std::wstring &path)
|
||||
{
|
||||
bool writable = false;
|
||||
@@ -338,13 +343,9 @@ int main(int argc, char *argv[])
|
||||
QString dataPath =
|
||||
instanceID.isEmpty() ? application.applicationDirPath()
|
||||
: QDir::fromNativeSeparators(
|
||||
#if QT_VERSION >= 0x050000
|
||||
QStandardPaths::writableLocation(QStandardPaths::DataLocation)
|
||||
#else
|
||||
QDesktopServices::storageLocation(QDesktopServices::DataLocation)
|
||||
#endif
|
||||
QStandardPaths::writableLocation(QStandardPaths::DataLocation)
|
||||
+ "/" + instanceID
|
||||
);
|
||||
);
|
||||
application.setProperty("dataPath", dataPath);
|
||||
|
||||
if (!QDir(dataPath).exists()) {
|
||||
@@ -367,23 +368,29 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!bootstrap()) { // requires gameinfo to be initialised!
|
||||
return -1;
|
||||
}
|
||||
|
||||
LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
qDebug("ssl support: %d", QSslSocket::supportsSsl());
|
||||
#endif
|
||||
|
||||
qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath())));
|
||||
qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators(application.applicationDirPath())));
|
||||
QPixmap pixmap(":/MO/gui/splash");
|
||||
QSplashScreen splash(pixmap);
|
||||
splash.show();
|
||||
|
||||
cleanupDir();
|
||||
try {
|
||||
if (!bootstrap()) { // requires gameinfo to be initialised!
|
||||
return -1;
|
||||
}
|
||||
|
||||
LogBuffer::init(100, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log");
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
qDebug("ssl support: %d", QSslSocket::supportsSsl());
|
||||
#endif
|
||||
|
||||
qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath())));
|
||||
qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators(application.applicationDirPath())));
|
||||
splash.show();
|
||||
|
||||
cleanupDir();
|
||||
} catch (const std::exception &e) {
|
||||
reportError(e.what());
|
||||
return 1;
|
||||
}
|
||||
|
||||
{ // extend path to include dll directory so plugins don't need a manifest
|
||||
// (using AddDllDirectory would be an alternative to this but it seems fairly complicated esp.
|
||||
@@ -406,8 +413,6 @@ int main(int argc, char *argv[])
|
||||
::SetEnvironmentVariableW(L"PATH", newPath.c_str());
|
||||
}
|
||||
|
||||
registerMetaTypes();
|
||||
|
||||
QStringList arguments = application.arguments();
|
||||
|
||||
bool forcePrimary = false;
|
||||
@@ -430,9 +435,9 @@ int main(int argc, char *argv[])
|
||||
} // we continue for the primary instance OR if MO has been called with parameters
|
||||
|
||||
QSettings settings(dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()), QSettings::IniFormat);
|
||||
|
||||
qDebug("initializing core");
|
||||
OrganizerCore organizer(settings);
|
||||
|
||||
qDebug("initialize plugins");
|
||||
PluginContainer pluginContainer(&organizer);
|
||||
pluginContainer.loadPlugins();
|
||||
|
||||
@@ -491,21 +496,26 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
IPluginGame *game = organizer.managedGame();
|
||||
|
||||
if (!settings.contains("game_edition")) {
|
||||
std::vector<std::wstring> editions = GameInfo::instance().getSteamVariants();
|
||||
QStringList editions = game->gameVariants();
|
||||
if (editions.size() > 1) {
|
||||
SelectionDialog selection(QObject::tr("Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)"), nullptr);
|
||||
int index = 0;
|
||||
for (auto iter = editions.begin(); iter != editions.end(); ++iter) {
|
||||
selection.addChoice(ToQString(*iter), "", index++);
|
||||
for (const QString &edition : editions) {
|
||||
selection.addChoice(edition, "", index++);
|
||||
}
|
||||
if (selection.exec() == QDialog::Rejected) {
|
||||
return -1;
|
||||
} else {
|
||||
settings.setValue("game_edition", selection.getChoiceData().toInt());
|
||||
settings.setValue("game_edition", selection.getChoiceString());
|
||||
}
|
||||
}
|
||||
}
|
||||
game->setGameVariant(settings.value("game_edition").toString());
|
||||
|
||||
|
||||
#pragma message("edition isn't used?")
|
||||
qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(gamePath)));
|
||||
|
||||
@@ -516,7 +526,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
// if we have a command line parameter, it is either a nxm link or
|
||||
// a binary to start
|
||||
if ((arguments.size() > 1) && (!isNxmLink(arguments.at(1)))) {
|
||||
if ((arguments.size() > 1)
|
||||
&& !isNxmLink(arguments.at(1))) {
|
||||
QString exeName = arguments.at(1);
|
||||
qDebug("starting %s from command line", qPrintable(exeName));
|
||||
arguments.removeFirst(); // remove application name (ModOrganizer.exe)
|
||||
@@ -531,6 +542,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
NexusInterface::instance()->getAccessManager()->startLoginCheck();
|
||||
|
||||
qDebug("initializing tutorials");
|
||||
TutorialManager::init(qApp->applicationDirPath() + "/" + QString::fromStdWString(AppConfig::tutorialsPath()) + "/",
|
||||
&organizer);
|
||||
@@ -553,8 +566,8 @@ int main(int argc, char *argv[])
|
||||
qDebug("displaying main window");
|
||||
mainWindow.show();
|
||||
|
||||
if ((arguments.size() > 1) &&
|
||||
(isNxmLink(arguments.at(1)))) {
|
||||
if ((arguments.size() > 1)
|
||||
&& isNxmLink(arguments.at(1))) {
|
||||
qDebug("starting download from command line: %s", qPrintable(arguments.at(1)));
|
||||
organizer.externalMessage(arguments.at(1));
|
||||
}
|
||||
|
||||
+223
-147
File diff suppressed because it is too large
Load Diff
+12
-4
@@ -30,7 +30,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QProgressBar>
|
||||
#include <QTranslator>
|
||||
#include <QPluginLoader>
|
||||
#include "executableslist.h"
|
||||
#include "modlist.h"
|
||||
#include "pluginlist.h"
|
||||
#include "plugincontainer.h"
|
||||
@@ -93,8 +92,6 @@ public:
|
||||
void refreshDataTree();
|
||||
void refreshSaveList();
|
||||
|
||||
void setExecutablesList(const ExecutablesList &executablesList);
|
||||
|
||||
void setModListSorting(int index);
|
||||
void setESPListSorting(int index);
|
||||
|
||||
@@ -124,6 +121,7 @@ public:
|
||||
|
||||
virtual MOBase::DelayedFileWriterBase &archivesWriter() override { return m_ArchiveListWriter; }
|
||||
|
||||
void updateWindowTitle(const QString &accountName, bool premium);
|
||||
public slots:
|
||||
|
||||
void displayColumnSelection(const QPoint &pos);
|
||||
@@ -329,6 +327,17 @@ private:
|
||||
|
||||
MOBase::DelayedFileWriter m_ArchiveListWriter;
|
||||
|
||||
enum class ShortcutType {
|
||||
Toolbar,
|
||||
Desktop,
|
||||
StartMenu
|
||||
};
|
||||
|
||||
void addWindowsLink(ShortcutType const);
|
||||
|
||||
Executable const &getSelectedExecutable() const;
|
||||
Executable &getSelectedExecutable();
|
||||
|
||||
private slots:
|
||||
|
||||
void showMessage(const QString &message);
|
||||
@@ -525,7 +534,6 @@ private slots: // ui slots
|
||||
void on_categoriesOrBtn_toggled(bool checked);
|
||||
void on_managedArchiveLabel_linkHovered(const QString &link);
|
||||
void on_manageArchivesBox_toggled(bool checked);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ bool MOApplication::setStyleFile(const QString &styleName)
|
||||
updateStyle(styleName);
|
||||
}
|
||||
} else {
|
||||
setStyle(new ProxyStyle(QStyleFactory::create(m_DefaultStyle)));
|
||||
setStyleSheet("");
|
||||
}
|
||||
return true;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user