mirror of
https://github.com/ModOrganizer2/modorganizer.git
synced 2026-07-27 13:58:24 -07:00
Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dce78b62b8 | ||
|
|
af6e1c3ab4 | ||
|
|
50325c8fc2 | ||
|
|
7a382eab75 | ||
|
|
8e6868bf88 | ||
|
|
a891146446 | ||
|
|
72f14df8a7 | ||
|
|
0fa7155eb8 | ||
|
|
c6c61ce792 | ||
|
|
ef801879ab | ||
|
|
1e6c5f7c25 | ||
|
|
49e1dd23b6 | ||
|
|
9c31cfa915 | ||
|
|
91dd38cb29 |
@@ -12,7 +12,9 @@ SUBDIRS = bsatk \
|
||||
plugins \
|
||||
proxydll \
|
||||
nxmhandler \
|
||||
BossDummy
|
||||
BossDummy \
|
||||
pythonRunner \
|
||||
esptk
|
||||
|
||||
hookdll.depends = shared
|
||||
organizer.depends = shared, uibase, plugins
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ void DownloadListWidgetDelegate::paint(QPainter *painter, const QStyleOptionView
|
||||
}
|
||||
m_InstallLabel->setPalette(labelPalette);
|
||||
if (m_Manager->isInfoIncomplete(downloadIndex)) {
|
||||
m_NameLabel->setText("<img src=\":/MO/gui/resources/dialog-warning_16.png\" /> " + m_NameLabel->text());
|
||||
m_NameLabel->setText("<img src=\":/MO/gui/warning_16\" /> " + m_NameLabel->text());
|
||||
}
|
||||
} else {
|
||||
m_InstallLabel->setVisible(false);
|
||||
|
||||
@@ -137,7 +137,7 @@ void DownloadListWidgetCompactDelegate::paint(QPainter *painter, const QStyleOpt
|
||||
m_DoneLabel->setForegroundRole(QPalette::WindowText);
|
||||
}
|
||||
if (m_Manager->isInfoIncomplete(downloadIndex)) {
|
||||
m_NameLabel->setText("<img src=\":/MO/gui/resources/dialog-warning_16.png\"/> " + m_NameLabel->text());
|
||||
m_NameLabel->setText("<img src=\":/MO/gui/warning_16\"/> " + m_NameLabel->text());
|
||||
}
|
||||
} else {
|
||||
m_DoneLabel->setVisible(false);
|
||||
|
||||
@@ -53,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;
|
||||
@@ -98,6 +99,7 @@ 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;
|
||||
@@ -283,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)
|
||||
{
|
||||
@@ -331,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()));
|
||||
@@ -343,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);
|
||||
@@ -597,6 +604,20 @@ 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())) {
|
||||
@@ -1034,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) {
|
||||
@@ -1121,6 +1144,19 @@ 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());
|
||||
if (deltaTime > 5) {
|
||||
emit downloadSpeed(serverMap["Name"].toString(), (info->m_TotalSize - info->m_PreResumeSize) / deltaTime);
|
||||
} // no division by zero please! Also, if the download is shorter than a few seconds, the result is way to inprecise
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setState(info, STATE_FETCHINGMODINFO); // need to set this state before changing the file name, otherwise .unfinished is appended
|
||||
|
||||
QString newName = getFileNameFromNetworkReply(reply);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -214,6 +219,13 @@ public:
|
||||
*/
|
||||
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
|
||||
*
|
||||
@@ -297,6 +309,7 @@ public:
|
||||
int indexByName(const QString &fileName) const;
|
||||
|
||||
void pauseAll();
|
||||
|
||||
signals:
|
||||
|
||||
void aboutToUpdate();
|
||||
@@ -322,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:
|
||||
|
||||
/**
|
||||
|
||||
+35
-15
@@ -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);
|
||||
}
|
||||
@@ -206,7 +207,7 @@ QString canonicalize(const QString &name)
|
||||
}
|
||||
|
||||
|
||||
QStringList InstallationManager::extractFiles(const QStringList &filesOrig)
|
||||
QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool flatten)
|
||||
{
|
||||
QStringList files;
|
||||
|
||||
@@ -222,20 +223,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 +259,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 +409,7 @@ void InstallationManager::report7ZipError(LPCWSTR errorMessage)
|
||||
#else
|
||||
reportError(QString::fromUtf16(errorMessage));
|
||||
#endif
|
||||
m_CurrentArchive->cancel();
|
||||
}
|
||||
|
||||
|
||||
@@ -422,7 +431,7 @@ QString InstallationManager::generateBackupName(const QString &directoryName) co
|
||||
|
||||
bool InstallationManager::testOverwrite(GuessedValue<QString> &modName) const
|
||||
{
|
||||
QString targetDirectory = QDir::fromNativeSeparators(m_ModsDirectory.mid(0).append("\\").append(modName));
|
||||
QString targetDirectory = QDir::fromNativeSeparators(m_ModsDirectory + "\\" + modName);
|
||||
|
||||
while (QDir(targetDirectory).exists()) {
|
||||
QueryOverwriteDialog overwriteDialog(m_ParentWidget);
|
||||
@@ -527,6 +536,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 {
|
||||
@@ -654,8 +664,11 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
|
||||
modName.update(guessedModName, GUESS_GOOD);
|
||||
}
|
||||
|
||||
qDebug("using mod name \"%s\" (id %d)", modName->toUtf8().constData(), modID);
|
||||
m_CurrentFile = fileInfo.fileName();
|
||||
m_CurrentFile = fileInfo.absoluteFilePath();
|
||||
if (fileInfo.dir() == QDir(ToQString(GameInfo::instance().getDownloadDir()))) {
|
||||
m_CurrentFile = fileInfo.fileName();
|
||||
}
|
||||
qDebug("using mod name \"%s\" (id %d) -> %s", modName->toUtf8().constData(), modID, qPrintable(m_CurrentFile));
|
||||
|
||||
// open the archive and construct the directory tree the installers work on
|
||||
bool archiveOpen = m_CurrentArchive->open(ToWString(QDir::toNativeSeparators(fileName)).c_str(),
|
||||
@@ -716,6 +729,13 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
|
||||
qPrintable(installer->name()), e.what());
|
||||
}
|
||||
|
||||
// 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) {
|
||||
QFile::remove(QDir::tempPath() + "/" + tempFile);
|
||||
}
|
||||
|
||||
|
||||
// act upon the installation result. at this point the files have already been
|
||||
// extracted to the correct location
|
||||
switch (installResult) {
|
||||
|
||||
@@ -57,6 +57,11 @@ public:
|
||||
|
||||
~InstallationManager();
|
||||
|
||||
/**
|
||||
* @brief update the directory where mods are to be installed
|
||||
* @param modsDirectory the mod directory
|
||||
* @note this is called a lot, probably redundantly
|
||||
*/
|
||||
void setModsDirectory(const QString &modsDirectory) { m_ModsDirectory = modsDirectory; }
|
||||
|
||||
/**
|
||||
@@ -114,7 +119,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
|
||||
|
||||
+6
-15
@@ -182,16 +182,7 @@ void cleanupDir()
|
||||
"QtXml4.dll",
|
||||
"QtWebKit4.dll",
|
||||
"qjpeg4.dll",
|
||||
/* "dlls/phonon4.dll",
|
||||
"dlls/QtCore4.dll",
|
||||
"dlls/QtGui4.dll",
|
||||
"dlls/QtNetwork4.dll",
|
||||
"dlls/QtXml4.dll",
|
||||
"dlls/QtXmlPatterns4.dll",
|
||||
"dlls/QtWebKit4.dll",
|
||||
"dlls/QtDeclarative4.dll",
|
||||
"dlls/QtScript4.dll",
|
||||
"dlls/QtSql4.dll"*/
|
||||
"NCC/GamebryoBase.dll"
|
||||
};
|
||||
|
||||
static const int NUM_FILES = sizeof(fileNames) / sizeof(QString);
|
||||
@@ -283,15 +274,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 +395,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;
|
||||
|
||||
|
||||
+85
-24
@@ -104,6 +104,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "modeltest.h"
|
||||
#endif // TEST_MODELS
|
||||
|
||||
#pragma warning( disable : 4428 )
|
||||
|
||||
using namespace MOBase;
|
||||
using namespace MOShared;
|
||||
@@ -143,7 +144,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
m_InstallationManager(this), m_Translator(NULL), m_TranslatorQt(NULL),
|
||||
m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()),
|
||||
m_CurrentProfile(NULL), m_AskForNexusPW(false), m_LoginAttempted(false),
|
||||
m_ArchivesInit(false), m_ContextItem(NULL), m_CurrentSaveView(NULL),
|
||||
m_ArchivesInit(false), m_ContextItem(NULL), m_ContextAction(NULL), m_CurrentSaveView(NULL),
|
||||
m_GameInfo(new GameInfoImpl())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
@@ -212,12 +213,15 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
NexusInterface::instance()->setCacheDirectory(m_Settings.getCacheDirectory());
|
||||
NexusInterface::instance()->setNMMVersion(m_Settings.getNMMVersion());
|
||||
|
||||
m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
|
||||
|
||||
updateDownloadListDelegate();
|
||||
|
||||
ui->savegameList->installEventFilter(this);
|
||||
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*)));
|
||||
|
||||
@@ -259,6 +263,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
|
||||
|
||||
connect(&TutorialManager::instance(), SIGNAL(windowTutorialFinished(QString)), this, SLOT(windowTutorialFinished(QString)));
|
||||
|
||||
connect(ui->toolBar, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(toolBar_customContextMenuRequested(QPoint)));
|
||||
|
||||
connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString)));
|
||||
|
||||
m_CheckBSATimer.setSingleShot(true);
|
||||
@@ -1035,7 +1041,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();
|
||||
@@ -1120,6 +1126,8 @@ IModInterface *MainWindow::createMod(GuessedValue<QString> &name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
|
||||
|
||||
/* QString fixedName = name;
|
||||
fixDirectoryName(fixedName);
|
||||
unsigned int index = ModInfo::getIndex(fixedName);
|
||||
@@ -1323,17 +1331,6 @@ void MainWindow::setExecutableIndex(int index)
|
||||
executableBox->setCurrentIndex(1);
|
||||
}
|
||||
|
||||
const Executable &selectedExecutable = executableBox->itemData(executableBox->currentIndex()).value<Executable>();
|
||||
|
||||
QIcon addIcon(":/MO/gui/link");
|
||||
QIcon removeIcon(":/MO/gui/remove");
|
||||
|
||||
QFileInfo linkDesktopFile(QDir::fromNativeSeparators(getDesktopDirectory()) + "/" + selectedExecutable.m_Title + ".lnk");
|
||||
QFileInfo linkMenuFile(QDir::fromNativeSeparators(getStartMenuDirectory()) + "/" + selectedExecutable.m_Title + ".lnk");
|
||||
|
||||
ui->linkButton->menu()->actions().at(0)->setIcon(selectedExecutable.m_Toolbar ? removeIcon : addIcon);
|
||||
ui->linkButton->menu()->actions().at(1)->setIcon(linkDesktopFile.exists() ? removeIcon : addIcon);
|
||||
ui->linkButton->menu()->actions().at(2)->setIcon(linkMenuFile.exists() ? removeIcon : addIcon);
|
||||
}
|
||||
|
||||
|
||||
@@ -1766,14 +1763,14 @@ void MainWindow::checkBSAList()
|
||||
|
||||
if (item->checkState(0) == Qt::Unchecked) {
|
||||
if (m_DefaultArchives.contains(filename)) {
|
||||
item->setIcon(0, QIcon(":/MO/gui/resources/dialog-warning.png"));
|
||||
item->setIcon(0, QIcon(":/MO/gui/warning"));
|
||||
item->setToolTip(0, tr("This bsa is enabled in the ini file so it may be required!"));
|
||||
modWarning = true;
|
||||
} else {
|
||||
QString espName = filename.mid(0, filename.length() - 3).append("esp").toLower();
|
||||
QString esmName = filename.mid(0, filename.length() - 3).append("esm").toLower();
|
||||
if (m_PluginList.isEnabled(espName) || m_PluginList.isEnabled(esmName)) {
|
||||
item->setIcon(0, QIcon(":/MO/gui/resources/dialog-warning.png"));
|
||||
item->setIcon(0, QIcon(":/MO/gui/warning"));
|
||||
item->setToolTip(0, tr("This archive will still be loaded since there is a plugin of the same name but "
|
||||
"its files will not follow installation order!"));
|
||||
modWarning = true;
|
||||
@@ -1788,7 +1785,7 @@ void MainWindow::checkBSAList()
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
ui->tabWidget->setTabIcon(1, QIcon(":/MO/gui/resources/dialog-warning.png"));
|
||||
ui->tabWidget->setTabIcon(1, QIcon(":/MO/gui/warning"));
|
||||
} else {
|
||||
ui->tabWidget->setTabIcon(1, QIcon());
|
||||
}
|
||||
@@ -2590,6 +2587,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) {
|
||||
@@ -2732,8 +2730,13 @@ void MainWindow::reinstallMod_clicked()
|
||||
QString installationFile = modInfo->getInstallationFile();
|
||||
if (installationFile.length() != 0) {
|
||||
QString fullInstallationFile;
|
||||
if (QFileInfo(installationFile).isAbsolute()) {
|
||||
fullInstallationFile = installationFile;
|
||||
QFileInfo fileInfo(installationFile);
|
||||
if (fileInfo.isAbsolute()) {
|
||||
if (fileInfo.exists()) {
|
||||
fullInstallationFile = installationFile;
|
||||
} else {
|
||||
fullInstallationFile = m_DownloadManager.getOutputDirectory().append("/").append(fileInfo.fileName());
|
||||
}
|
||||
} else {
|
||||
fullInstallationFile = m_DownloadManager.getOutputDirectory().append("/").append(installationFile);
|
||||
}
|
||||
@@ -3016,6 +3019,9 @@ void MainWindow::createModFromOverwrite()
|
||||
}
|
||||
|
||||
IModInterface *newMod = createMod(name);
|
||||
if (newMod == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(m_ContextRow);
|
||||
|
||||
@@ -3306,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 {
|
||||
@@ -3314,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()));
|
||||
@@ -3338,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()));
|
||||
@@ -3592,12 +3613,19 @@ 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());
|
||||
QString oldCacheDirectory(m_Settings.getCacheDirectory());
|
||||
bool proxy = m_Settings.useProxy();
|
||||
m_Settings.query(this);
|
||||
m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
|
||||
fixCategories();
|
||||
refreshFilters();
|
||||
if (QDir::fromNativeSeparators(m_DownloadManager.getOutputDirectory()) != QDir::fromNativeSeparators(m_Settings.getDownloadDirectory())) {
|
||||
@@ -4098,7 +4126,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)));
|
||||
@@ -4136,7 +4163,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();
|
||||
@@ -4149,8 +4175,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());
|
||||
}
|
||||
}
|
||||
@@ -4468,6 +4495,25 @@ void MainWindow::unlockESPIndex()
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::removeFromToolbar()
|
||||
{
|
||||
Executable &exe = m_ExecutablesList.find(m_ContextAction->text());
|
||||
exe.m_Toolbar = false;
|
||||
updateToolBar();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::toolBar_customContextMenuRequested(const QPoint &point)
|
||||
{
|
||||
QAction *action = ui->toolBar->actionAt(point);
|
||||
if (action->objectName().startsWith("custom_")) {
|
||||
m_ContextAction = action;
|
||||
QMenu menu;
|
||||
menu.addAction(tr("Remove"), this, SLOT(removeFromToolbar()));
|
||||
menu.exec(ui->toolBar->mapToGlobal(point));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_espList_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
m_ContextRow = m_PluginListSortProxy->mapToSource(ui->espList->indexAt(pos)).row();
|
||||
@@ -4539,3 +4585,18 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index)
|
||||
m_ModListSortProxy->setSourceModel(&m_ModList);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_linkButton_pressed()
|
||||
{
|
||||
const Executable &selectedExecutable = ui->executablesListBox->itemData(ui->executablesListBox->currentIndex()).value<Executable>();
|
||||
|
||||
QIcon addIcon(":/MO/gui/link");
|
||||
QIcon removeIcon(":/MO/gui/remove");
|
||||
|
||||
QFileInfo linkDesktopFile(QDir::fromNativeSeparators(getDesktopDirectory()) + "/" + selectedExecutable.m_Title + ".lnk");
|
||||
QFileInfo linkMenuFile(QDir::fromNativeSeparators(getStartMenuDirectory()) + "/" + selectedExecutable.m_Title + ".lnk");
|
||||
|
||||
ui->linkButton->menu()->actions().at(0)->setIcon(selectedExecutable.m_Toolbar ? removeIcon : addIcon);
|
||||
ui->linkButton->menu()->actions().at(1)->setIcon(linkDesktopFile.exists() ? removeIcon : addIcon);
|
||||
ui->linkButton->menu()->actions().at(2)->setIcon(linkMenuFile.exists() ? removeIcon : addIcon);
|
||||
}
|
||||
|
||||
@@ -276,6 +276,8 @@ private:
|
||||
|
||||
int m_ContextRow;
|
||||
QTreeWidgetItem *m_ContextItem;
|
||||
QAction *m_ContextAction;
|
||||
|
||||
int m_SelectedSaveGame;
|
||||
|
||||
Settings m_Settings;
|
||||
@@ -452,6 +454,11 @@ private slots:
|
||||
*/
|
||||
void allowListResize();
|
||||
|
||||
void downloadSpeed(const QString &serverName, int bytesPerSecond);
|
||||
|
||||
void toolBar_customContextMenuRequested(const QPoint &point);
|
||||
void removeFromToolbar();
|
||||
|
||||
private slots: // ui slots
|
||||
// actions
|
||||
void on_actionAdd_Profile_triggered();
|
||||
@@ -483,6 +490,7 @@ private slots: // ui slots
|
||||
void on_displayCategoriesBtn_toggled(bool checked);
|
||||
void on_groupCombo_currentIndexChanged(int index);
|
||||
void on_categoriesList_itemSelectionChanged();
|
||||
void on_linkButton_pressed();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
+10
-4
@@ -927,8 +927,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>
|
||||
@@ -994,7 +1000,7 @@ p, li { white-space: pre-wrap; }
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::PreventContextMenu</enum>
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Tool Bar</string>
|
||||
@@ -1159,7 +1165,7 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/MO/gui/resources/dialog-warning.png</normaloff>:/MO/gui/resources/dialog-warning.png</iconset>
|
||||
<normaloff>:/MO/gui/warning</normaloff>:/MO/gui/warning</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No Problems</string>
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
+1
-1
@@ -809,7 +809,7 @@ public:
|
||||
virtual void setNeverEndorse() {}
|
||||
virtual bool remove() { return false; }
|
||||
virtual void endorse(bool) {}
|
||||
virtual QString name() const { return tr("Overwrite"); }
|
||||
virtual QString name() const { return "Overwrite"; }
|
||||
virtual QString notes() const { return ""; }
|
||||
virtual QDateTime creationTime() const { return QDateTime::currentDateTime(); }
|
||||
virtual QString absolutePath() const;
|
||||
|
||||
+31
-5
@@ -38,6 +38,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QFileSystemModel>
|
||||
#include <Shlwapi.h>
|
||||
#include <sstream>
|
||||
#include <QInputDialog>
|
||||
|
||||
|
||||
using QtJson::Json;
|
||||
@@ -146,7 +147,7 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
|
||||
|
||||
QTabWidget *tabWidget = findChild<QTabWidget*>("tabWidget");
|
||||
tabWidget->setTabEnabled(TAB_TEXTFILES, textFileList->count() != 0);
|
||||
tabWidget->setTabEnabled(TAB_INIFILES, (iniFileList->count() != 0) || (iniTweaksList->count() != 0));
|
||||
//tabWidget->setTabEnabled(TAB_INIFILES, (iniFileList->count() != 0) || (iniTweaksList->count() != 0));
|
||||
tabWidget->setTabEnabled(TAB_IMAGES, thumbnailArea->count() != 0);
|
||||
tabWidget->setTabEnabled(TAB_ESPS, (inactiveESPList->count() != 0) || (activeESPList->count() != 0));
|
||||
tabWidget->setTabEnabled(TAB_CONFLICTS, m_Origin != NULL);
|
||||
@@ -409,8 +410,6 @@ void ModInfoDialog::openTextFile(const QString &fileName)
|
||||
|
||||
void ModInfoDialog::openIniFile(const QString &fileName)
|
||||
{
|
||||
QPushButton* saveButton = findChild<QPushButton*>("saveButton");
|
||||
|
||||
QFile iniFile(fileName);
|
||||
iniFile.open(QIODevice::ReadOnly);
|
||||
QByteArray buffer = iniFile.readAll();
|
||||
@@ -421,7 +420,7 @@ void ModInfoDialog::openIniFile(const QString &fileName)
|
||||
iniFileView->setProperty("encoding", codec->name());
|
||||
iniFile.close();
|
||||
|
||||
saveButton->setEnabled(false);
|
||||
ui->saveButton->setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -515,8 +514,9 @@ void ModInfoDialog::saveCurrentIniFile()
|
||||
{
|
||||
QVariant fileNameVar = ui->iniFileView->property("currentFile");
|
||||
QVariant encodingVar = ui->iniFileView->property("encoding");
|
||||
if (fileNameVar.isValid()) {
|
||||
if (fileNameVar.isValid() && !fileNameVar.toString().isEmpty()) {
|
||||
QString fileName = fileNameVar.toString();
|
||||
QDir().mkpath(QFileInfo(fileName).absolutePath());
|
||||
QFile txtFile(fileName);
|
||||
txtFile.open(QIODevice::WriteOnly);
|
||||
txtFile.resize(0);
|
||||
@@ -1171,3 +1171,29 @@ void ModInfoDialog::on_prevButton_clicked()
|
||||
emit modOpenPrev();
|
||||
this->accept();
|
||||
}
|
||||
|
||||
|
||||
void ModInfoDialog::createTweak()
|
||||
{
|
||||
QString name = QInputDialog::getText(this, tr("Name"), tr("Please enter a name"));
|
||||
if (!fixDirectoryName(name)) {
|
||||
QMessageBox::critical(this, tr("Error"), tr("Invalid name. Must be a valid file name"));
|
||||
return;
|
||||
} else if (name.isEmpty()) {
|
||||
return;
|
||||
} else if (ui->iniTweaksList->findItems(name, Qt::MatchFixedString).count() != 0) {
|
||||
QMessageBox::critical(this, tr("Error"), tr("A tweak by that name exists"));
|
||||
return;
|
||||
}
|
||||
|
||||
QListWidgetItem *newTweak = new QListWidgetItem(name);
|
||||
newTweak->setData(Qt::UserRole, "INI Tweaks/" + name + ".ini");
|
||||
ui->iniTweaksList->addItem(newTweak);
|
||||
}
|
||||
|
||||
void ModInfoDialog::on_iniTweaksList_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QMenu menu;
|
||||
menu.addAction(tr("Create Tweak"), this, SLOT(createTweak()));
|
||||
menu.exec(ui->iniTweaksList->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
@@ -186,6 +186,9 @@ private slots:
|
||||
|
||||
void on_prevButton_clicked();
|
||||
|
||||
void on_iniTweaksList_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
void createTweak();
|
||||
private:
|
||||
|
||||
Ui::ModInfoDialog *ui;
|
||||
|
||||
+4
-10
@@ -106,6 +106,9 @@
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -224,16 +227,7 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user