mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e6c5f7c25 | ||
|
|
49e1dd23b6 | ||
|
|
9c31cfa915 | ||
|
|
91dd38cb29 | ||
|
|
bf0db9c218 | ||
|
|
8fcf21e771 | ||
|
|
b46b2fe6f2 | ||
|
|
e91eebefbe | ||
|
|
2e605b275b | ||
|
|
87f4e2df26 | ||
|
|
9272013103 |
@@ -46,6 +46,7 @@ public:
|
||||
static const int CATEGORY_SPECIAL_UPDATEAVAILABLE = 10002;
|
||||
static const int CATEGORY_SPECIAL_NOCATEGORY = 10003;
|
||||
static const int CATEGORY_SPECIAL_CONFLICT = 10004;
|
||||
static const int CATEGORY_SPECIAL_NOTENDORSED = 10005;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ QVariant DownloadList::headerData(int section, Qt::Orientation orientation, int
|
||||
if ((role == Qt::DisplayRole) &&
|
||||
(orientation == Qt::Horizontal)) {
|
||||
switch (section) {
|
||||
case 0: return tr("Name");
|
||||
case 1: return tr("Filetime");
|
||||
case COL_NAME: return tr("Name");
|
||||
case COL_FILETIME: return tr("Filetime");
|
||||
default: return tr("Done");
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -34,6 +34,14 @@ class DownloadList : public QAbstractTableModel
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum EColumn {
|
||||
COL_NAME = 0,
|
||||
COL_FILETIME,
|
||||
COL_STATUS
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "downloadlistsortproxy.h"
|
||||
#include "downloadlist.h"
|
||||
|
||||
DownloadListSortProxy::DownloadListSortProxy(const DownloadManager *manager, QObject *parent)
|
||||
: QSortFilterProxyModel(parent), m_Manager(manager), m_CurrentFilter()
|
||||
@@ -30,18 +31,21 @@ void DownloadListSortProxy::updateFilter(const QString &filter)
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
bool DownloadListSortProxy::lessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const
|
||||
{
|
||||
int leftIndex = sourceModel()->data(left).toInt();
|
||||
int rightIndex = sourceModel()->data(right).toInt();
|
||||
|
||||
if (left.column() == 0) {
|
||||
if (left.column() == DownloadList::COL_NAME) {
|
||||
return m_Manager->getFileName(leftIndex).compare(m_Manager->getFileName(rightIndex), Qt::CaseInsensitive) < 0;
|
||||
} else if (left.column() == 1) {
|
||||
return leftIndex < rightIndex;
|
||||
} else {
|
||||
} else if (left.column() == DownloadList::COL_FILETIME) {
|
||||
return m_Manager->getFileTime(leftIndex) < m_Manager->getFileTime(rightIndex);
|
||||
} else if (left.column() == DownloadList::COL_STATUS) {
|
||||
return m_Manager->getState(leftIndex) < m_Manager->getState(rightIndex);
|
||||
} else {
|
||||
return leftIndex < rightIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ DownloadListWidgetDelegate::DownloadListWidgetDelegate(DownloadManager *manager,
|
||||
: QItemDelegate(parent), m_Manager(manager), m_ItemWidget(new DownloadListWidget), m_ContextRow(0), m_View(view)
|
||||
{
|
||||
m_NameLabel = m_ItemWidget->findChild<QLabel*>("nameLabel");
|
||||
m_SizeLabel = m_ItemWidget->findChild<QLabel*>("sizeLabel");
|
||||
m_Progress = m_ItemWidget->findChild<QProgressBar*>("downloadProgress");
|
||||
m_InstallLabel = m_ItemWidget->findChild<QLabel*>("installLabel");
|
||||
|
||||
@@ -100,6 +101,7 @@ void DownloadListWidgetDelegate::paint(QPainter *painter, const QStyleOptionView
|
||||
name.append("...");
|
||||
}
|
||||
m_NameLabel->setText(name);
|
||||
m_SizeLabel->setText(QString::number(m_Manager->getFileSize(downloadIndex) / 1024));
|
||||
DownloadManager::DownloadState state = m_Manager->getState(downloadIndex);
|
||||
if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)) {
|
||||
QPalette labelPalette;
|
||||
|
||||
@@ -101,6 +101,7 @@ private:
|
||||
DownloadManager *m_Manager;
|
||||
|
||||
QLabel *m_NameLabel;
|
||||
QLabel *m_SizeLabel;
|
||||
QProgressBar *m_Progress;
|
||||
QLabel *m_InstallLabel;
|
||||
int m_ContextRow;
|
||||
|
||||
+48
-17
@@ -42,23 +42,54 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>323</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Placeholder</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>323</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Placeholder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="sizeLabel">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>KB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
|
||||
@@ -44,6 +44,7 @@ DownloadListWidgetCompactDelegate::DownloadListWidgetCompactDelegate(DownloadMan
|
||||
: QItemDelegate(parent), m_Manager(manager), m_ItemWidget(new DownloadListWidgetCompact), m_View(view)
|
||||
{
|
||||
m_NameLabel = m_ItemWidget->findChild<QLabel*>("nameLabel");
|
||||
m_SizeLabel = m_ItemWidget->findChild<QLabel*>("sizeLabel");
|
||||
m_Progress = m_ItemWidget->findChild<QProgressBar*>("downloadProgress");
|
||||
m_DoneLabel = m_ItemWidget->findChild<QLabel*>("doneLabel");
|
||||
|
||||
@@ -106,7 +107,13 @@ void DownloadListWidgetCompactDelegate::paint(QPainter *painter, const QStyleOpt
|
||||
name.append("...");
|
||||
}
|
||||
m_NameLabel->setText(name);
|
||||
|
||||
DownloadManager::DownloadState state = m_Manager->getState(downloadIndex);
|
||||
|
||||
if ((m_SizeLabel != NULL) && (state >= DownloadManager::STATE_READY)) {
|
||||
m_SizeLabel->setText(QString::number(m_Manager->getFileSize(downloadIndex) / 1048576));
|
||||
}
|
||||
|
||||
if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)) {
|
||||
m_DoneLabel->setVisible(true);
|
||||
m_Progress->setVisible(false);
|
||||
|
||||
@@ -100,6 +100,7 @@ private:
|
||||
DownloadManager *m_Manager;
|
||||
|
||||
QLabel *m_NameLabel;
|
||||
QLabel *m_SizeLabel;
|
||||
QProgressBar *m_Progress;
|
||||
QLabel *m_DoneLabel;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>315</width>
|
||||
<height>22</height>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
@@ -23,14 +23,23 @@
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
@@ -48,6 +57,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="doneLabel">
|
||||
<property name="sizePolicy">
|
||||
@@ -60,24 +82,24 @@
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>118</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>118</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>118</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>118</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
|
||||
+86
-2
@@ -33,6 +33,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <boost/bind.hpp>
|
||||
#include <regex>
|
||||
#include <QMessageBox>
|
||||
#include <QCoreApplication>
|
||||
|
||||
|
||||
using QtJson::Json;
|
||||
@@ -52,6 +53,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Ne
|
||||
DownloadInfo *info = new DownloadInfo;
|
||||
info->m_DownloadID = s_NextDownloadID++;
|
||||
info->m_StartTime.start();
|
||||
info->m_PreResumeSize = 0LL;
|
||||
info->m_Progress = 0;
|
||||
info->m_ResumePos = 0;
|
||||
info->m_ModID = modID;
|
||||
@@ -96,6 +98,8 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con
|
||||
|
||||
info->m_DownloadID = s_NextDownloadID++;
|
||||
info->m_Output.setFileName(filePath);
|
||||
info->m_TotalSize = QFileInfo(filePath).size();
|
||||
info->m_PreResumeSize = info->m_TotalSize;
|
||||
info->m_ModID = metaFile.value("modID", 0).toInt();
|
||||
info->m_FileID = metaFile.value("fileID", 0).toInt();
|
||||
info->m_CurrentUrl = 0;
|
||||
@@ -162,12 +166,41 @@ bool DownloadManager::downloadsInProgress()
|
||||
{
|
||||
for (QVector<DownloadInfo*>::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter) {
|
||||
if ((*iter)->m_State < STATE_READY) {
|
||||
// return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DownloadManager::pauseAll()
|
||||
{
|
||||
// first loop: pause all downloads
|
||||
for (int i = 0; i < m_ActiveDownloads.count(); ++i) {
|
||||
if (m_ActiveDownloads[i]->m_State < STATE_READY) {
|
||||
pauseDownload(i);
|
||||
}
|
||||
}
|
||||
|
||||
::Sleep(100);
|
||||
|
||||
bool done = false;
|
||||
// further loops: busy waiting for all downloads to complete. This could be neater...
|
||||
while (!done) {
|
||||
QCoreApplication::processEvents();
|
||||
done = true;
|
||||
foreach (DownloadInfo *info, m_ActiveDownloads) {
|
||||
if ((info->m_State < STATE_CANCELED) ||
|
||||
(info->m_State != STATE_FETCHINGFILEINFO) || (info->m_State != STATE_FETCHINGMODINFO)) {
|
||||
done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
::Sleep(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DownloadManager::setOutputDirectory(const QString &outputDirectory)
|
||||
{
|
||||
@@ -252,6 +285,7 @@ bool DownloadManager::addDownload(const QStringList &URLs,
|
||||
return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, nexusInfo);
|
||||
}
|
||||
|
||||
|
||||
bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName,
|
||||
int modID, int fileID, const NexusInfo &nexusInfo)
|
||||
{
|
||||
@@ -300,6 +334,8 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl
|
||||
mode |= QIODevice::Append;
|
||||
}
|
||||
|
||||
newDownload->m_StartTime.start();
|
||||
|
||||
if (!newDownload->m_Output.open(mode)) {
|
||||
reportError(tr("failed to download %1: could not open output file: %2")
|
||||
.arg(reply->url().toString()).arg(newDownload->m_Output.fileName()));
|
||||
@@ -312,6 +348,8 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl
|
||||
connect(newDownload->m_Reply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
|
||||
|
||||
if (!resume) {
|
||||
newDownload->m_PreResumeSize = newDownload->m_Output.size();
|
||||
|
||||
emit aboutToUpdate();
|
||||
|
||||
m_ActiveDownloads.append(newDownload);
|
||||
@@ -456,8 +494,18 @@ void DownloadManager::pauseDownload(int index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DownloadManager::resumeDownload(int index)
|
||||
{
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
reportError(tr("invalid index %1").arg(index));
|
||||
return;
|
||||
}
|
||||
DownloadInfo *info = m_ActiveDownloads[index];
|
||||
info->m_Tries = AUTOMATIC_RETRIES;
|
||||
resumeDownloadInt(index);
|
||||
}
|
||||
|
||||
void DownloadManager::resumeDownloadInt(int index)
|
||||
{
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
reportError(tr("invalid index %1").arg(index));
|
||||
@@ -556,6 +604,29 @@ QString DownloadManager::getFileName(int index) const
|
||||
return m_ActiveDownloads.at(index)->m_FileName;
|
||||
}
|
||||
|
||||
QDateTime DownloadManager::getFileTime(int index) const
|
||||
{
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
throw MyException(tr("invalid index"));
|
||||
}
|
||||
|
||||
DownloadInfo *info = m_ActiveDownloads.at(index);
|
||||
if (!info->m_Created.isValid()) {
|
||||
info->m_Created = QFileInfo(info->m_Output).created();
|
||||
}
|
||||
|
||||
return info->m_Created;
|
||||
}
|
||||
|
||||
qint64 DownloadManager::getFileSize(int index) const
|
||||
{
|
||||
if ((index < 0) || (index >= m_ActiveDownloads.size())) {
|
||||
throw MyException(tr("invalid index"));
|
||||
}
|
||||
|
||||
return m_ActiveDownloads.at(index)->m_TotalSize;
|
||||
}
|
||||
|
||||
|
||||
int DownloadManager::getProgress(int index) const
|
||||
{
|
||||
@@ -984,6 +1055,8 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u
|
||||
|
||||
std::sort(resultList.begin(), resultList.end(), boost::bind(&DownloadManager::ServerByPreference, m_PreferredServers, _1, _2));
|
||||
|
||||
info.m_DownloadMap = resultList;
|
||||
|
||||
QStringList URLs;
|
||||
|
||||
foreach (const QVariant &server, resultList) {
|
||||
@@ -1071,6 +1144,17 @@ void DownloadManager::downloadFinished()
|
||||
createMetaFile(info);
|
||||
emit update(index);
|
||||
} else {
|
||||
|
||||
QString url = info->m_Urls[info->m_CurrentUrl];
|
||||
foreach (const QVariant &server, info->m_NexusInfo.m_DownloadMap) {
|
||||
QVariantMap serverMap = server.toMap();
|
||||
if (serverMap["URI"].toString() == url) {
|
||||
int deltaTime = info->m_StartTime.secsTo(QTime::currentTime());
|
||||
emit downloadSpeed(serverMap["Name"].toString(), (info->m_TotalSize - info->m_PreResumeSize) / deltaTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setState(info, STATE_FETCHINGMODINFO); // need to set this state before changing the file name, otherwise .unfinished is appended
|
||||
|
||||
QString newName = getFileNameFromNetworkReply(reply);
|
||||
|
||||
+28
-1
@@ -45,6 +45,7 @@ struct NexusInfo {
|
||||
QString m_Version;
|
||||
QString m_NewestVersion;
|
||||
QString m_FileName;
|
||||
QVariantList m_DownloadMap;
|
||||
bool m_Set;
|
||||
};
|
||||
Q_DECLARE_METATYPE(NexusInfo)
|
||||
@@ -82,6 +83,7 @@ private:
|
||||
QFile m_Output;
|
||||
QNetworkReply *m_Reply;
|
||||
QTime m_StartTime;
|
||||
qint64 m_PreResumeSize;
|
||||
int m_Progress;
|
||||
int m_ModID;
|
||||
int m_FileID;
|
||||
@@ -90,6 +92,9 @@ private:
|
||||
QStringList m_Urls;
|
||||
qint64 m_ResumePos;
|
||||
qint64 m_TotalSize;
|
||||
|
||||
QDateTime m_Created; // used as a cache in DownloadManager::getFileTime, may not be valid elsewhere
|
||||
|
||||
int m_Tries;
|
||||
bool m_ReQueried;
|
||||
|
||||
@@ -206,6 +211,21 @@ public:
|
||||
**/
|
||||
QString getFileName(int index) const;
|
||||
|
||||
/**
|
||||
* @brief retrieve the file size of the download specified by index
|
||||
*
|
||||
* @param index index of the file to look up
|
||||
* @return size of the file (total size during download)
|
||||
*/
|
||||
qint64 getFileSize(int index) const;
|
||||
|
||||
/**
|
||||
* @brief retrieve the creation time of the download specified by index
|
||||
* @param index index of the file to look up
|
||||
* @return size of the file (total size during download)
|
||||
*/
|
||||
QDateTime getFileTime(int index) const;
|
||||
|
||||
/**
|
||||
* @brief retrieve the current progress of the download specified by index
|
||||
*
|
||||
@@ -288,6 +308,8 @@ public:
|
||||
*/
|
||||
int indexByName(const QString &fileName) const;
|
||||
|
||||
void pauseAll();
|
||||
|
||||
signals:
|
||||
|
||||
void aboutToUpdate();
|
||||
@@ -313,6 +335,11 @@ signals:
|
||||
*/
|
||||
void stateChanged(int row, DownloadManager::DownloadState state);
|
||||
|
||||
/**
|
||||
* @brief emitted whenever a download completes successfully, reporting the download speed for the server used
|
||||
*/
|
||||
void downloadSpeed(const QString &serverName, int bytesPerSecond);
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
@@ -357,10 +384,10 @@ private slots:
|
||||
private:
|
||||
|
||||
void createMetaFile(DownloadInfo *info);
|
||||
// QString getOutputPath(const QUrl &url, const QString &fileName) const;
|
||||
QString getDownloadFileName(const QString &baseName) const;
|
||||
|
||||
void startDownload(QNetworkReply *reply, DownloadInfo *newDownload, bool resume);
|
||||
void resumeDownloadInt(int index);
|
||||
|
||||
/**
|
||||
* @brief start a download from a url
|
||||
|
||||
+23
-12
@@ -114,7 +114,8 @@ void InstallationManager::mapToArchive(const DirectoryTree::Node *node, std::wst
|
||||
for (DirectoryTree::const_node_iterator iter = node->nodesBegin(); iter != node->nodesEnd(); ++iter) {
|
||||
if ((*iter)->getData().index != -1) {
|
||||
data[(*iter)->getData().index]->setSkip(false);
|
||||
data[(*iter)->getData().index]->setOutputFileName(path.substr().append(ToWString((*iter)->getData().name)).c_str());
|
||||
std::wstring temp = path.substr().append(ToWString((*iter)->getData().name));
|
||||
data[(*iter)->getData().index]->setOutputFileName(temp.c_str());
|
||||
}
|
||||
mapToArchive(*iter, path.substr().append(ToWString((*iter)->getData().name)), data);
|
||||
}
|
||||
@@ -151,6 +152,7 @@ bool InstallationManager::unpackSingleFile(const QString &fileName)
|
||||
if (_wcsicmp(data[i]->getFileName(), ToWString(fileName).c_str()) == 0) {
|
||||
available = true;
|
||||
data[i]->setSkip(false);
|
||||
qDebug("usf %ls -> %s", data[i]->getFileName(), qPrintable(baseName));
|
||||
data[i]->setOutputFileName(ToWString(baseName).c_str());
|
||||
m_TempFilesToDelete.insert(baseName);
|
||||
} else {
|
||||
@@ -206,7 +208,7 @@ QString canonicalize(const QString &name)
|
||||
}
|
||||
|
||||
|
||||
QStringList InstallationManager::extractFiles(const QStringList &filesOrig)
|
||||
QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool flatten)
|
||||
{
|
||||
QStringList files;
|
||||
|
||||
@@ -222,20 +224,26 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig)
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (files.contains(ToQString(data[i]->getFileName()), Qt::CaseInsensitive)) {
|
||||
const wchar_t *baseName = wcsrchr(data[i]->getFileName(), '\\');
|
||||
if (baseName == NULL) {
|
||||
baseName = wcsrchr(data[i]->getFileName(), '/');
|
||||
const wchar_t *targetFile = data[i]->getFileName();
|
||||
if (flatten) {
|
||||
targetFile = wcsrchr(data[i]->getFileName(), '\\');
|
||||
if (targetFile == NULL) {
|
||||
targetFile = wcsrchr(data[i]->getFileName(), '/');
|
||||
}
|
||||
if (targetFile == NULL) {
|
||||
qCritical("failed to find backslash in %ls", data[i]->getFileName());
|
||||
continue;
|
||||
} else {
|
||||
// skip the slash
|
||||
++targetFile;
|
||||
}
|
||||
}
|
||||
if (baseName == NULL) {
|
||||
qCritical("failed to find backslash in %ls", data[i]->getFileName());
|
||||
continue;
|
||||
}
|
||||
data[i]->setOutputFileName(baseName);
|
||||
data[i]->setOutputFileName(targetFile);
|
||||
|
||||
result.append(QDir::tempPath().append("/").append(ToQString(baseName)));
|
||||
result.append(QDir::tempPath().append("/").append(ToQString(targetFile)));
|
||||
|
||||
data[i]->setSkip(false);
|
||||
m_TempFilesToDelete.insert(ToQString(baseName));
|
||||
m_TempFilesToDelete.insert(ToQString(targetFile));
|
||||
} else {
|
||||
data[i]->setSkip(true);
|
||||
}
|
||||
@@ -252,6 +260,7 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig)
|
||||
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();
|
||||
throw std::runtime_error("extracting failed");
|
||||
}
|
||||
|
||||
@@ -401,6 +410,7 @@ void InstallationManager::report7ZipError(LPCWSTR errorMessage)
|
||||
#else
|
||||
reportError(QString::fromUtf16(errorMessage));
|
||||
#endif
|
||||
m_CurrentArchive->cancel();
|
||||
}
|
||||
|
||||
|
||||
@@ -527,6 +537,7 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID,
|
||||
new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
|
||||
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::updateProgressFile),
|
||||
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::report7ZipError))) {
|
||||
m_InstallationProgress.hide();
|
||||
if (m_CurrentArchive->getLastError() == Archive::ERROR_EXTRACT_CANCELLED) {
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
* @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);
|
||||
virtual QStringList extractFiles(const QStringList &files, bool flatten);
|
||||
|
||||
/**
|
||||
* @brief installs an archive
|
||||
|
||||
+5
-5
@@ -283,15 +283,15 @@ void registerMetaTypes()
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MOApplication application(argc, argv);
|
||||
qApp->addLibraryPath(application.applicationDirPath() + "/dlls");
|
||||
|
||||
application.addLibraryPath(application.applicationDirPath() + "/dlls");
|
||||
|
||||
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
|
||||
|
||||
LogBuffer::init(20, QtDebugMsg, application.applicationDirPath() + "/logs/mo_interface.log");
|
||||
|
||||
qDebug("Working directory: %s", qPrintable(QDir::currentPath()));
|
||||
qDebug("MO at: %s", qPrintable(application.applicationDirPath()));
|
||||
qDebug("user name: %s", getenv("USERNAME"));
|
||||
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();
|
||||
@@ -404,7 +404,7 @@ int main(int argc, char *argv[])
|
||||
settings.setValue("gamePath", gamePath.toUtf8().constData());
|
||||
}
|
||||
|
||||
qDebug("managing game at %s", qPrintable(gamePath));
|
||||
qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(gamePath)));
|
||||
|
||||
ExecutablesList executablesList;
|
||||
|
||||
|
||||
+152
-58
@@ -100,6 +100,12 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
|
||||
#ifdef TEST_MODELS
|
||||
#include "modeltest.h"
|
||||
#endif // TEST_MODELS
|
||||
|
||||
#pragma warning( disable : 4428 )
|
||||
|
||||
using namespace MOBase;
|
||||
using namespace MOShared;
|
||||
|
||||
@@ -128,11 +134,6 @@ static bool isOnline()
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_MODELS
|
||||
#include "modeltest.h"
|
||||
#endif // TEST_MODELS
|
||||
|
||||
|
||||
MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget *parent)
|
||||
: QMainWindow(parent), ui(new Ui::MainWindow), m_Tutorial(this, "MainWindow"),
|
||||
m_ExeName(exeName), m_OldProfileIndex(-1),
|
||||
@@ -162,7 +163,6 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
updateProblemsButton();
|
||||
|
||||
updateToolBar();
|
||||
// ui->toolBar->blockSignals(true);
|
||||
|
||||
ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure);
|
||||
|
||||
@@ -181,43 +181,25 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
ui->modList->setItemDelegateForColumn(ModList::COL_FLAGS, new IconDelegate(ui->modList));
|
||||
//ui->modList->setAcceptDrops(true);
|
||||
ui->modList->header()->installEventFilter(&m_ModList);
|
||||
ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray());
|
||||
if (initSettings.contains("mod_list_state")) {
|
||||
ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray());
|
||||
}
|
||||
ui->modList->header()->setSectionHidden(0, false); // prevent the name-column from being hidden
|
||||
ui->modList->installEventFilter(&m_ModList);
|
||||
|
||||
// restoreState also seems to restores the resize mode from previous session,
|
||||
// I don't really like that
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
for (int i = 0; i < ui->modList->header()->count(); ++i) {
|
||||
ui->modList->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
ui->modList->header()->setSectionResizeMode(ModList::COL_NAME, QHeaderView::Stretch);
|
||||
#else
|
||||
for (int i = 0; i < ui->modList->header()->count(); ++i) {
|
||||
ui->modList->header()->setResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
ui->modList->header()->setResizeMode(ModList::COL_NAME, QHeaderView::Stretch);
|
||||
#endif
|
||||
|
||||
// set up plugin list
|
||||
m_PluginListSortProxy = new PluginListSortProxy(this);
|
||||
m_PluginListSortProxy->setSourceModel(&m_PluginList);
|
||||
|
||||
ui->espList->setModel(m_PluginListSortProxy);
|
||||
ui->espList->sortByColumn(PluginList::COL_PRIORITY, Qt::AscendingOrder);
|
||||
ui->espList->header()->restoreState(initSettings.value("plugin_list_state").toByteArray());
|
||||
if (initSettings.contains("plugin_list_state")) {
|
||||
ui->espList->header()->restoreState(initSettings.value("plugin_list_state").toByteArray());
|
||||
}
|
||||
ui->espList->installEventFilter(&m_PluginList);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
for (int i = 0; i < ui->espList->header()->count(); ++i) {
|
||||
ui->espList->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
ui->espList->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
#else
|
||||
for (int i = 0; i < ui->espList->header()->count(); ++i) {
|
||||
ui->espList->header()->setResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
ui->espList->header()->setResizeMode(0, QHeaderView::Stretch);
|
||||
#endif
|
||||
|
||||
resizeLists(initSettings.contains("mod_list_state"), initSettings.contains("plugin_list_state"));
|
||||
|
||||
|
||||
QMenu *linkMenu = new QMenu(this);
|
||||
linkMenu->addAction(QIcon(":/MO/gui/link"), tr("Toolbar"), this, SLOT(linkToolbar()));
|
||||
@@ -237,6 +219,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
ui->savegameList->setMouseTracking(true);
|
||||
|
||||
connect(&m_DownloadManager, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString)));
|
||||
connect(&m_DownloadManager, SIGNAL(downloadSpeed(QString,int)), this, SLOT(downloadSpeed(QString,int)));
|
||||
|
||||
connect(ui->savegameList, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(saveSelectionChanged(QListWidgetItem*)));
|
||||
|
||||
@@ -316,6 +299,72 @@ MainWindow::~MainWindow()
|
||||
delete m_DirectoryStructure;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::resizeLists(bool modListCustom, bool pluginListCustom)
|
||||
{
|
||||
if (!modListCustom) {
|
||||
// resize mod list to fit content
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
for (int i = 0; i < ui->modList->header()->count(); ++i) {
|
||||
ui->modList->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
ui->modList->header()->setSectionResizeMode(ModList::COL_NAME, QHeaderView::Stretch);
|
||||
#else
|
||||
for (int i = 0; i < ui->modList->header()->count(); ++i) {
|
||||
ui->modList->header()->setResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
ui->modList->header()->setResizeMode(ModList::COL_NAME, QHeaderView::Stretch);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!pluginListCustom) {
|
||||
// resize plugin list to fit content
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
for (int i = 0; i < ui->espList->header()->count(); ++i) {
|
||||
ui->espList->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
ui->espList->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
#else
|
||||
for (int i = 0; i < ui->espList->header()->count(); ++i) {
|
||||
ui->espList->header()->setResizeMode(i, QHeaderView::ResizeToContents);
|
||||
}
|
||||
ui->espList->header()->setResizeMode(0, QHeaderView::Stretch);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::allowListResize()
|
||||
{
|
||||
// allow resize on mod list
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
for (int i = 0; i < ui->modList->header()->count(); ++i) {
|
||||
ui->modList->header()->setSectionResizeMode(i, QHeaderView::Interactive);
|
||||
}
|
||||
ui->modList->header()->setSectionResizeMode(ui->modList->header()->count() - 1, QHeaderView::Stretch);
|
||||
#else
|
||||
for (int i = 0; i < ui->modList->header()->count(); ++i) {
|
||||
ui->modList->header()->setResizeMode(i, QHeaderView::Interactive);
|
||||
}
|
||||
ui->modList->header()->setResizeMode(ui->modList->header()->count() - 1, QHeaderView::Stretch);
|
||||
#endif
|
||||
|
||||
|
||||
// allow resize on plugin list
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
for (int i = 0; i < ui->espList->header()->count(); ++i) {
|
||||
ui->espList->header()->setSectionResizeMode(i, QHeaderView::Interactive);
|
||||
}
|
||||
ui->espList->header()->setSectionResizeMode(ui->espList->header()->count() - 1, QHeaderView::Stretch);
|
||||
#else
|
||||
for (int i = 0; i < ui->espList->header()->count(); ++i) {
|
||||
ui->espList->header()->setResizeMode(i, QHeaderView::Interactive);
|
||||
}
|
||||
ui->espList->header()->setResizeMode(ui->espList->header()->count() - 1, QHeaderView::Stretch);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::updateStyle(const QString&)
|
||||
{
|
||||
// no effect?
|
||||
@@ -540,9 +589,12 @@ void MainWindow::saveArchiveList()
|
||||
QFile archiveFile(m_CurrentProfile->getArchivesFileName());
|
||||
if (archiveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) {
|
||||
QTreeWidgetItem *item = ui->bsaList->topLevelItem(i);
|
||||
if ((item != NULL) && (item->checkState(0) == Qt::Checked)) {
|
||||
archiveFile.write(item->text(0).toUtf8().append("\r\n"));
|
||||
QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i);
|
||||
for (int j = 0; j < tlItem->childCount(); ++j) {
|
||||
QTreeWidgetItem *item = tlItem->child(j);
|
||||
if (item->checkState(0) == Qt::Checked) {
|
||||
archiveFile.write(item->text(0).toUtf8().append("\r\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -707,17 +759,22 @@ void MainWindow::showEvent(QShowEvent *event)
|
||||
// this has no visible impact when called before the ui is visible
|
||||
int grouping = m_Settings.directInterface().value("group_state").toInt();
|
||||
ui->groupCombo->setCurrentIndex(grouping);
|
||||
|
||||
allowListResize();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
if (m_DownloadManager.downloadsInProgress() &&
|
||||
QMessageBox::question(this, tr("Downloads in progress"),
|
||||
if (m_DownloadManager.downloadsInProgress()) {
|
||||
if (QMessageBox::question(this, tr("Downloads in progress"),
|
||||
tr("There are still downloads in progress, do you really want to quit?"),
|
||||
QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel) {
|
||||
event->ignore();
|
||||
return;
|
||||
event->ignore();
|
||||
return;
|
||||
} else {
|
||||
m_DownloadManager.pauseAll();
|
||||
}
|
||||
}
|
||||
|
||||
setCursor(Qt::WaitCursor);
|
||||
@@ -942,7 +999,7 @@ bool MainWindow::registerPlugin(QObject *plugin)
|
||||
QObject *proxiedPlugin = proxy->instantiate(pluginName);
|
||||
if (proxiedPlugin != NULL) {
|
||||
if (registerPlugin(proxiedPlugin)) {
|
||||
qDebug("loaded plugin \"%s\"", pluginName.toUtf8().constData());
|
||||
qDebug("loaded plugin \"%s\"", QDir::toNativeSeparators(pluginName).toUtf8().constData());
|
||||
} else {
|
||||
qWarning("plugin \"%s\" failed to load", pluginName.toUtf8().constData());
|
||||
}
|
||||
@@ -980,7 +1037,7 @@ void MainWindow::loadPlugins()
|
||||
}
|
||||
|
||||
QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
|
||||
qDebug("looking for plugins in %s", pluginPath.toUtf8().constData());
|
||||
qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData());
|
||||
QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot);
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
@@ -993,7 +1050,7 @@ void MainWindow::loadPlugins()
|
||||
pluginName.toUtf8().constData(), pluginLoader.errorString().toUtf8().constData());
|
||||
} else {
|
||||
if (registerPlugin(pluginLoader.instance())) {
|
||||
qDebug("loaded plugin \"%s\"", pluginName.toUtf8().constData());
|
||||
qDebug("loaded plugin \"%s\"", QDir::toNativeSeparators(pluginName).toUtf8().constData());
|
||||
} else {
|
||||
m_UnloadedPlugins.push_back(pluginName);
|
||||
qWarning("plugin \"%s\" failed to load", pluginName.toUtf8().constData());
|
||||
@@ -1570,7 +1627,8 @@ void MainWindow::refreshESPList()
|
||||
m_CurrentProfile->writeModlist();
|
||||
|
||||
// clear list
|
||||
m_PluginList.refresh(m_CurrentProfile->getName(), *m_DirectoryStructure,
|
||||
m_PluginList.refresh(m_CurrentProfile->getName(),
|
||||
*m_DirectoryStructure,
|
||||
m_CurrentProfile->getPluginsFileName(),
|
||||
m_CurrentProfile->getLoadOrderFileName(),
|
||||
m_CurrentProfile->getLockedOrderFileName());
|
||||
@@ -1794,6 +1852,10 @@ void MainWindow::readSettings()
|
||||
restoreGeometry(settings.value("window_geometry").toByteArray());
|
||||
}
|
||||
|
||||
if (settings.contains("window_split")) {
|
||||
ui->splitter->restoreState(settings.value("window_split").toByteArray());
|
||||
}
|
||||
|
||||
bool filtersVisible = settings.value("filters_visible", false).toBool();
|
||||
setCategoryListVisible(filtersVisible);
|
||||
ui->displayCategoriesBtn->setChecked(filtersVisible);
|
||||
@@ -1832,7 +1894,8 @@ void MainWindow::storeSettings()
|
||||
settings.setValue("compact_downloads", ui->compactBox->isChecked());
|
||||
settings.setValue("ask_for_nexuspw", m_AskForNexusPW);
|
||||
|
||||
settings.setValue("window_geometry", this->saveGeometry());
|
||||
settings.setValue("window_geometry", saveGeometry());
|
||||
settings.setValue("window_split", ui->splitter->saveState());
|
||||
|
||||
settings.setValue("filters_visible", ui->displayCategoriesBtn->isChecked());
|
||||
|
||||
@@ -1955,6 +2018,9 @@ QString MainWindow::shortDescription(unsigned int key) const
|
||||
case PROBLEM_PLUGINSNOTLOADED: {
|
||||
return tr("Some plugins could not be loaded");
|
||||
} break;
|
||||
default: {
|
||||
return tr("Description missing");
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1969,15 +2035,18 @@ QString MainWindow::fullDescription(unsigned int key) const
|
||||
result += "<ul>";
|
||||
return result;
|
||||
} break;
|
||||
default: {
|
||||
return tr("Description missing");
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::hasGuidedFix(unsigned int key) const
|
||||
bool MainWindow::hasGuidedFix(unsigned int) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::startGuidedFix(unsigned int key) const
|
||||
void MainWindow::startGuidedFix(unsigned int) const
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2523,6 +2592,7 @@ void MainWindow::refreshFilters()
|
||||
addFilterItem(NULL, tr("<Update>"), CategoryFactory::CATEGORY_SPECIAL_UPDATEAVAILABLE);
|
||||
addFilterItem(NULL, tr("<No category>"), CategoryFactory::CATEGORY_SPECIAL_NOCATEGORY);
|
||||
addFilterItem(NULL, tr("<Conflicted>"), CategoryFactory::CATEGORY_SPECIAL_CONFLICT);
|
||||
addFilterItem(NULL, tr("<Not Endorsed>"), CategoryFactory::CATEGORY_SPECIAL_NOTENDORSED);
|
||||
|
||||
std::set<int> categoriesUsed;
|
||||
for (unsigned int modIdx = 0; modIdx < ModInfo::getNumMods(); ++modIdx) {
|
||||
@@ -2949,6 +3019,9 @@ void MainWindow::createModFromOverwrite()
|
||||
}
|
||||
|
||||
IModInterface *newMod = createMod(name);
|
||||
if (newMod == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(m_ContextRow);
|
||||
|
||||
@@ -3239,6 +3312,17 @@ void MainWindow::exportModListCSV()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void addMenuAsPushButton(QMenu *menu, QMenu *subMenu)
|
||||
{
|
||||
QPushButton *pushBtn = new QPushButton(subMenu->title());
|
||||
pushBtn->setMenu(subMenu);
|
||||
QWidgetAction *action = new QWidgetAction(menu);
|
||||
action->setDefaultWidget(pushBtn);
|
||||
menu->addAction(action);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
try {
|
||||
@@ -3247,6 +3331,7 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
|
||||
m_ContextRow = mapToModel(&m_ModList, modList->indexAt(pos)).row();
|
||||
|
||||
QMenu menu;
|
||||
|
||||
menu.addAction(tr("Install Mod..."), this, SLOT(installMod_clicked()));
|
||||
|
||||
menu.addAction(tr("Enable all visible"), this, SLOT(enableVisibleMods()));
|
||||
@@ -3271,13 +3356,16 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
|
||||
menu.addAction(tr("Restore Backup"), this, SLOT(restoreBackup_clicked()));
|
||||
menu.addAction(tr("Remove Backup..."), this, SLOT(removeMod_clicked()));
|
||||
} else {
|
||||
QMenu *addCategoryMenu = menu.addMenu(tr("Set Category"));
|
||||
// Set categories is a separate menu connected to a push button. This way it doesn't simply close every time you hover the mouse outside
|
||||
QMenu *addCategoryMenu = new QMenu(tr("Set Category"));
|
||||
addCategories(addCategoryMenu, 0);
|
||||
connect(addCategoryMenu, SIGNAL(aboutToHide()), this, SLOT(saveCategories()));
|
||||
addMenuAsPushButton(&menu, addCategoryMenu);
|
||||
|
||||
QMenu *primaryCategoryMenu = menu.addMenu(tr("Primary Category"));
|
||||
QMenu *primaryCategoryMenu = new QMenu(tr("Primary Category"));
|
||||
connect(primaryCategoryMenu, SIGNAL(aboutToShow()), this, SLOT(addPrimaryCategoryCandidates()));
|
||||
connect(primaryCategoryMenu, SIGNAL(aboutToHide()), this, SLOT(savePrimaryCategory()));
|
||||
addMenuAsPushButton(&menu, primaryCategoryMenu);
|
||||
|
||||
menu.addAction(tr("Rename Mod..."), this, SLOT(renameMod_clicked()));
|
||||
menu.addAction(tr("Remove Mod..."), this, SLOT(removeMod_clicked()));
|
||||
@@ -3525,6 +3613,12 @@ void MainWindow::linkMenu()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::downloadSpeed(const QString &serverName, int bytesPerSecond)
|
||||
{
|
||||
m_Settings.setDownloadSpeed(serverName, bytesPerSecond);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionSettings_triggered()
|
||||
{
|
||||
QString oldModDirectory(m_Settings.getModDirectory());
|
||||
@@ -4031,7 +4125,6 @@ void MainWindow::updateDownloadListDelegate()
|
||||
ui->downloadView->setModel(sortProxy);
|
||||
ui->downloadView->sortByColumn(1, Qt::AscendingOrder);
|
||||
ui->downloadView->header()->resizeSections(QHeaderView::Fixed);
|
||||
// ui->downloadView->setFirstColumnSpanned(0, QModelIndex(), true);
|
||||
|
||||
connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), this, SLOT(installDownload(int)));
|
||||
connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), &m_DownloadManager, SLOT(queryInfo(int)));
|
||||
@@ -4069,7 +4162,6 @@ void MainWindow::modDetailsUpdated(bool)
|
||||
void MainWindow::nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant userData, QVariant resultData, int)
|
||||
{
|
||||
m_ModsToUpdate -= modIDs.size();
|
||||
|
||||
QVariantList resultList = resultData.toList();
|
||||
for (auto iter = resultList.begin(); iter != resultList.end(); ++iter) {
|
||||
QVariantMap result = iter->toMap();
|
||||
@@ -4082,8 +4174,9 @@ void MainWindow::nxmUpdatesAvailable(const std::vector<int> &modIDs, QVariant us
|
||||
for (auto iter = info.begin(); iter != info.end(); ++iter) {
|
||||
(*iter)->setNewestVersion(VersionInfo(result["version"].toString()));
|
||||
(*iter)->setNexusDescription(result["description"].toString());
|
||||
if (NexusInterface::instance()->getAccessManager()->loggedIn()) {
|
||||
// don't use endorsement info if we're not logged in
|
||||
if (NexusInterface::instance()->getAccessManager()->loggedIn() &&
|
||||
result.contains("voted_by_user")) {
|
||||
// don't use endorsement info if we're not logged in or if the response doesn't contain it
|
||||
(*iter)->setIsEndorsed(result["voted_by_user"].toBool());
|
||||
}
|
||||
}
|
||||
@@ -4254,10 +4347,9 @@ bool MainWindow::extractProgress(QProgressDialog &progress, int percentage, std:
|
||||
|
||||
void MainWindow::extractBSATriggered()
|
||||
{
|
||||
QTreeWidgetItem *item = ui->bsaList->topLevelItem(m_ContextRow);
|
||||
QTreeWidgetItem *item = m_ContextItem;
|
||||
|
||||
QString targetFolder = FileDialogMemory::getExistingDirectory("extractBSA", this, tr("Extract BSA"));
|
||||
|
||||
if (!targetFolder.isEmpty()) {
|
||||
BSA::Archive archive;
|
||||
QString originPath = QDir::fromNativeSeparators(ToQString(m_DirectoryStructure->getOriginByName(ToWString(item->text(1))).getPath()));
|
||||
@@ -4273,10 +4365,8 @@ void MainWindow::extractBSATriggered()
|
||||
progress.setMaximum(100);
|
||||
progress.setValue(0);
|
||||
progress.show();
|
||||
|
||||
archive.extractAll(QDir::toNativeSeparators(targetFolder).toUtf8().constData(),
|
||||
boost::bind(&MainWindow::extractProgress, this, boost::ref(progress), _1, _2));
|
||||
|
||||
if (result == BSA::ERROR_INVALIDHASHES) {
|
||||
reportError(tr("This archive contains invalid hashes. Some files may be broken."));
|
||||
}
|
||||
@@ -4318,7 +4408,9 @@ void MainWindow::displayColumnSelection(const QPoint &pos)
|
||||
|
||||
void MainWindow::on_bsaList_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
m_ContextRow = ui->bsaList->indexOfTopLevelItem(ui->bsaList->itemAt(pos));
|
||||
m_ContextItem = ui->bsaList->itemAt(pos);
|
||||
|
||||
// m_ContextRow = ui->bsaList->indexOfTopLevelItem(ui->bsaList->itemAt(pos));
|
||||
|
||||
QMenu menu;
|
||||
menu.addAction(tr("Extract..."), this, SLOT(extractBSATriggered()));
|
||||
@@ -4424,6 +4516,8 @@ void MainWindow::on_espList_customContextMenuRequested(const QPoint &pos)
|
||||
}
|
||||
}
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
if (hasLocked) {
|
||||
menu.addAction(tr("Unlock load order"), this, SLOT(unlockESPIndex()));
|
||||
}
|
||||
|
||||
@@ -442,6 +442,18 @@ private slots:
|
||||
|
||||
void expandModList(const QModelIndex &index);
|
||||
|
||||
/**
|
||||
* @brief resize columns in mod list and plugin list to content
|
||||
*/
|
||||
void resizeLists(bool modListCustom, bool pluginListCustom);
|
||||
|
||||
/**
|
||||
* @brief allow columns in mod list and plugin list to be resized
|
||||
*/
|
||||
void allowListResize();
|
||||
|
||||
void downloadSpeed(const QString &serverName, int bytesPerSecond);
|
||||
|
||||
private slots: // ui slots
|
||||
// actions
|
||||
void on_actionAdd_Profile_triggered();
|
||||
|
||||
+10
-4
@@ -320,7 +320,7 @@ p, li { white-space: pre-wrap; }
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>10</number>
|
||||
<number>20</number>
|
||||
</attribute>
|
||||
<attribute name="headerShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
@@ -861,7 +861,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>200</number>
|
||||
<number>400</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
@@ -972,8 +972,14 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
|
||||
+2
-2
@@ -410,7 +410,7 @@ void ModInfoRegular::nxmDescriptionAvailable(int, QVariant, QVariant resultData)
|
||||
QVariantMap result = resultData.toMap();
|
||||
m_NewestVersion.parse(result["version"].toString());
|
||||
m_NexusDescription = result["description"].toString();
|
||||
if (m_EndorsedState != ENDORSED_NEVER) {
|
||||
if ((m_EndorsedState != ENDORSED_NEVER) && (result.contains("voted_by_user"))) {
|
||||
m_EndorsedState = result["voted_by_user"].toBool() ? ENDORSED_TRUE : ENDORSED_FALSE;
|
||||
}
|
||||
m_LastNexusQuery = QDateTime::currentDateTime();
|
||||
@@ -759,7 +759,7 @@ std::vector<QString> ModInfoRegular::getIniTweaks() const
|
||||
|
||||
if (numTweaks != 0) {
|
||||
qDebug("%d active ini tweaks in %s",
|
||||
numTweaks, metaFileName.toUtf8().constData());
|
||||
numTweaks, QDir::toNativeSeparators(metaFileName).toUtf8().constData());
|
||||
}
|
||||
|
||||
for (int i = 0; i < numTweaks; ++i) {
|
||||
|
||||
+21
-1
@@ -747,7 +747,7 @@ bool ModList::eventFilter(QObject *obj, QEvent *event)
|
||||
if (event->type() == QEvent::ContextMenu) {
|
||||
QContextMenuEvent *contextEvent = static_cast<QContextMenuEvent*>(event);
|
||||
QWidget *object = qobject_cast<QWidget*>(obj);
|
||||
if (object != NULL) {
|
||||
if ((object != NULL) && (contextEvent->reason() == QContextMenuEvent::Mouse)) {
|
||||
emit requestColumnSelect(object->mapToGlobal(contextEvent->pos()));
|
||||
|
||||
return true;
|
||||
@@ -801,6 +801,26 @@ bool ModList::eventFilter(QObject *obj, QEvent *event)
|
||||
removeRow(rows[0].data(Qt::UserRole + 1).toInt(), QModelIndex());
|
||||
}
|
||||
return true;
|
||||
} else if (keyEvent->key() == Qt::Key_Space) {
|
||||
QItemSelectionModel *selectionModel = itemView->selectionModel();
|
||||
const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel*>(selectionModel->model());
|
||||
|
||||
QModelIndex minRow, maxRow;
|
||||
foreach (QModelIndex idx, selectionModel->selectedRows()) {
|
||||
if (proxyModel != NULL) {
|
||||
idx = proxyModel->mapToSource(idx);
|
||||
}
|
||||
if (!minRow.isValid() || (idx.row() < minRow.row())) {
|
||||
minRow = idx;
|
||||
}
|
||||
if (!maxRow.isValid() || (idx.row() > maxRow.row())) {
|
||||
maxRow = idx;
|
||||
}
|
||||
int oldState = idx.data(Qt::CheckStateRole).toInt();
|
||||
setData(idx, oldState == Qt::Unchecked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
|
||||
}
|
||||
emit dataChanged(minRow, maxRow);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QObject::eventFilter(obj, event);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user