From 38391b10e968d22f0e5c731642407412178f29b5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 10 May 2018 09:21:02 -0500 Subject: Fix plugin lock slot typo --- src/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2830c776..5b6525bd 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4637,7 +4637,7 @@ void MainWindow::on_espList_customContextMenuRequested(const QPoint &pos) menu.addAction(tr("Unlock load order"), this, SLOT(unlockESPIndex())); } if (hasUnlocked) { - menu.addAction(tr("Lock load order"), this, SLOT(f())); + menu.addAction(tr("Lock load order"), this, SLOT(lockESPIndex())); } try { -- cgit v1.3.1 From 6617be8ef9a015dd4109729155fc9a772997b5ed Mon Sep 17 00:00:00 2001 From: Diana Date: Fri, 18 May 2018 07:45:13 -0400 Subject: Fix a memory leak in updateToolBar updateToolBar was creating new QActions and QWidgets every call, without cleaning them up. The spacer, help widgets, and toolbuttons only need to be created once. Those have been moved out into the MainWindow constructor updateToolBar is called in various places, importantly when adding/removing executable shortcuts. Also adds a deleteLater() call to clean up executable shortcut actions. --- src/mainwindow.cpp | 66 ++++++++++++++++++++++++++++-------------------------- src/mainwindow.h | 2 ++ 2 files changed, 36 insertions(+), 32 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5b6525bd..4d1a3b03 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -242,7 +242,28 @@ MainWindow::MainWindow(QSettings &initSettings updateProblemsButton(); - updateToolBar(); + // Setup toolbar + QWidget *spacer = new QWidget(ui->toolBar); + spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + QWidget *widget = ui->toolBar->widgetForAction(ui->actionTool); + QToolButton *toolBtn = qobject_cast(widget); + + if (toolBtn->menu() == nullptr) { + actionToToolButton(ui->actionTool); + } + + actionToToolButton(ui->actionHelp); + createHelpWidget(); + + for (QAction *action : ui->toolBar->actions()) { + if (action->isSeparator()) { + // insert spacers + ui->toolBar->insertWidget(action, spacer); + m_Sep = action; + // m_Sep would only use the last seperator anyway, and we only have the one anyway? + break; + } + } TaskProgressManager::instance().tryCreateTaskbar(); @@ -560,41 +581,22 @@ void MainWindow::updateToolBar() for (QAction *action : ui->toolBar->actions()) { if (action->objectName().startsWith("custom__")) { ui->toolBar->removeAction(action); + action->deleteLater(); } } - QWidget *spacer = new QWidget(ui->toolBar); - spacer->setObjectName("custom__spacer"); - spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - QWidget *widget = ui->toolBar->widgetForAction(ui->actionTool); - QToolButton *toolBtn = qobject_cast(widget); - - if (toolBtn->menu() == nullptr) { - actionToToolButton(ui->actionTool); - } - - actionToToolButton(ui->actionHelp); - createHelpWidget(); - - for (QAction *action : ui->toolBar->actions()) { - if (action->isSeparator()) { - // insert spacers - ui->toolBar->insertWidget(action, spacer); - - std::vector::iterator begin, end; - m_OrganizerCore.executablesList()->getExecutables(begin, end); - for (auto iter = begin; iter != end; ++iter) { - if (iter->isShownOnToolbar()) { - QAction *exeAction = new QAction(iconForExecutable(iter->m_BinaryInfo.filePath()), - iter->m_Title, - ui->toolBar); - exeAction->setObjectName(QString("custom__") + iter->m_Title); - if (!connect(exeAction, SIGNAL(triggered()), this, SLOT(startExeAction()))) { - qDebug("failed to connect trigger?"); - } - ui->toolBar->insertAction(action, exeAction); - } + std::vector::iterator begin, end; + m_OrganizerCore.executablesList()->getExecutables(begin, end); + for (auto iter = begin; iter != end; ++iter) { + if (iter->isShownOnToolbar()) { + QAction *exeAction = new QAction(iconForExecutable(iter->m_BinaryInfo.filePath()), + iter->m_Title, + ui->toolBar); + exeAction->setObjectName(QString("custom__") + iter->m_Title); + if (!connect(exeAction, SIGNAL(triggered()), this, SLOT(startExeAction()))) { + qDebug("failed to connect trigger?"); } + ui->toolBar->insertAction(m_Sep, exeAction); } } } diff --git a/src/mainwindow.h b/src/mainwindow.h index bbff0d93..02094344 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -304,6 +304,8 @@ private: Ui::MainWindow *ui; + QAction *m_Sep; // Executable Shortcuts are added after this. Non owning. + bool m_WasVisible; MOBase::TutorialControl m_Tutorial; -- cgit v1.3.1 From 4b66c6c1ef52a68cbca752be69fc57b47a25104c Mon Sep 17 00:00:00 2001 From: Al12rs Date: Sun, 20 May 2018 23:02:50 +0200 Subject: Added "Open Plugins folder" option to Open folder menu. --- src/mainwindow.cpp | 17 +++++++++-------- src/mainwindow.h | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4d1a3b03..a428d5b3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3155,6 +3155,13 @@ void MainWindow::openInstallFolder() ::ShellExecuteW(nullptr, L"explore", ToWString(qApp->applicationDirPath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); } +void MainWindow::openPluginsFolder() +{ + QString pluginsPath = QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()); + ::ShellExecuteW(nullptr, L"explore", ToWString(pluginsPath).c_str(), nullptr, nullptr, SW_SHOWNORMAL); +} + + void MainWindow::openProfileFolder() { ::ShellExecuteW(nullptr, L"explore", ToWString(m_OrganizerCore.currentProfile()->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); @@ -3366,15 +3373,9 @@ QMenu *MainWindow::openFolderMenu() FolderMenu->addAction(tr("Open MO2 Install folder"), this, SLOT(openInstallFolder())); - FolderMenu->addAction(tr("Open MO2 Logs folder"), this, SLOT(openLogsFolder())); - - - - - - - + FolderMenu->addAction(tr("Open MO2 Plugins folder"), this, SLOT(openPluginsFolder())); + FolderMenu->addAction(tr("Open MO2 Logs folder"), this, SLOT(openLogsFolder())); return FolderMenu; diff --git a/src/mainwindow.h b/src/mainwindow.h index 02094344..737a1534 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -500,6 +500,7 @@ private slots: void openInstanceFolder(); void openLogsFolder(); void openInstallFolder(); + void openPluginsFolder(); void openDownloadsFolder(); void openProfileFolder(); void openGameFolder(); -- cgit v1.3.1 From ddb40b712edf0676f6083a0ecd5a67509e60e6fe Mon Sep 17 00:00:00 2001 From: Al12rs Date: Fri, 25 May 2018 15:33:53 +0200 Subject: *Avoided some unnecessary refreshes while removing mods. *Added "Visit on Nexus" menu entry in the downloads tab. *Added confirmation message when deleting a single download. *Changed text of messages to more easily distinguish deleting from hiding. --- src/downloadlistwidget.cpp | 20 +++++++++++++++++--- src/downloadlistwidget.h | 6 ++++-- src/downloadlistwidgetcompact.cpp | 33 ++++++++++++++++++++++----------- src/downloadlistwidgetcompact.h | 7 ++++--- src/downloadmanager.cpp | 35 ++++++++++++++++++++++++++++++++--- src/downloadmanager.h | 2 ++ src/mainwindow.cpp | 11 +++++++---- 7 files changed, 88 insertions(+), 26 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/downloadlistwidget.cpp b/src/downloadlistwidget.cpp index d7bd01bb..75470056 100644 --- a/src/downloadlistwidget.cpp +++ b/src/downloadlistwidget.cpp @@ -245,7 +245,11 @@ void DownloadListWidgetDelegate::issueQueryInfo() void DownloadListWidgetDelegate::issueDelete() { - emit removeDownload(m_ContextRow, true); + if (QMessageBox::question(nullptr, tr("Delete Files?"), + tr("This will permanently delete the selected download."), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + emit removeDownload(m_ContextRow, true); + } } void DownloadListWidgetDelegate::issueRemoveFromView() @@ -263,6 +267,11 @@ void DownloadListWidgetDelegate::issueRestoreToViewAll() emit restoreDownload(-1); } +void DownloadListWidgetDelegate::issueVisitOnNexus() +{ + emit visitOnNexus(m_ContextRow); +} + void DownloadListWidgetDelegate::issueCancel() { @@ -281,7 +290,7 @@ void DownloadListWidgetDelegate::issueResume() void DownloadListWidgetDelegate::issueDeleteAll() { - if (QMessageBox::question(nullptr, tr("Are you sure?"), + if (QMessageBox::question(nullptr, tr("Delete Files?"), tr("This will remove all finished downloads from this list and from disk."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { emit removeDownload(-1, true); @@ -290,7 +299,7 @@ void DownloadListWidgetDelegate::issueDeleteAll() void DownloadListWidgetDelegate::issueDeleteCompleted() { - if (QMessageBox::question(nullptr, tr("Are you sure?"), + if (QMessageBox::question(nullptr, tr("Delete Files?"), tr("This will remove all installed downloads from this list and from disk."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { emit removeDownload(-2, true); @@ -340,7 +349,12 @@ bool DownloadListWidgetDelegate::editorEvent(QEvent *event, QAbstractItemModel * menu.addAction(tr("Install"), this, SLOT(issueInstall())); if (m_Manager->isInfoIncomplete(m_ContextRow)) { menu.addAction(tr("Query Info"), this, SLOT(issueQueryInfo())); + }else { + menu.addAction(tr("Visit on Nexus"), this,SLOT(issueVisitOnNexus())); } + + menu.addSeparator(); + menu.addAction(tr("Delete"), this, SLOT(issueDelete())); if (hidden) { menu.addAction(tr("Un-Hide"), this, SLOT(issueRestoreToView())); diff --git a/src/downloadlistwidget.h b/src/downloadlistwidget.h index 6e628cc7..e2746f3a 100644 --- a/src/downloadlistwidget.h +++ b/src/downloadlistwidget.h @@ -71,6 +71,7 @@ signals: void cancelDownload(int index); void pauseDownload(int index); void resumeDownload(int index); + void visitOnNexus(int index); protected: @@ -80,7 +81,7 @@ protected: private: - + void drawCache(QPainter *painter, const QStyleOptionViewItem &option, const QPixmap &cache) const; private slots: @@ -89,7 +90,8 @@ private slots: void issueDelete(); void issueRemoveFromView(); void issueRestoreToView(); - void issueRestoreToViewAll(); + void issueRestoreToViewAll(); + void issueVisitOnNexus(); void issueCancel(); void issuePause(); void issueResume(); diff --git a/src/downloadlistwidgetcompact.cpp b/src/downloadlistwidgetcompact.cpp index 97e3655b..cdce8d7f 100644 --- a/src/downloadlistwidgetcompact.cpp +++ b/src/downloadlistwidgetcompact.cpp @@ -209,7 +209,11 @@ void DownloadListWidgetCompactDelegate::issueQueryInfo() void DownloadListWidgetCompactDelegate::issueDelete() { - emit removeDownload(m_ContextIndex.row(), true); + if (QMessageBox::question(nullptr, tr("Are you sure?"), + tr("This will permanently delete the selected download."), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + emit removeDownload(m_ContextIndex.row(), true); + } } void DownloadListWidgetCompactDelegate::issueRemoveFromView() @@ -217,6 +221,11 @@ void DownloadListWidgetCompactDelegate::issueRemoveFromView() emit removeDownload(m_ContextIndex.row(), false); } +void DownloadListWidgetCompactDelegate::issueVisitOnNexus() +{ + emit visitOnNexus(m_ContextIndex.row()); +} + void DownloadListWidgetCompactDelegate::issueRestoreToView() { emit restoreDownload(m_ContextIndex.row()); @@ -305,7 +314,10 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem menu.addAction(tr("Install"), this, SLOT(issueInstall())); if (m_Manager->isInfoIncomplete(m_ContextIndex.row())) { menu.addAction(tr("Query Info"), this, SLOT(issueQueryInfo())); + }else { + menu.addAction(tr("Visit on Nexus"), this, SLOT(issueVisitOnNexus())); } + menu.addSeparator(); menu.addAction(tr("Delete"), this, SLOT(issueDelete())); if (hidden) { menu.addAction(tr("Un-Hide"), this, SLOT(issueRestoreToView())); @@ -324,15 +336,15 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem } menu.addAction(tr("Delete Installed..."), this, SLOT(issueDeleteCompleted())); menu.addAction(tr("Delete All..."), this, SLOT(issueDeleteAll())); - if (!hidden) { - menu.addSeparator(); - menu.addAction(tr("Hide Installed..."), this, SLOT(issueRemoveFromViewCompleted())); - menu.addAction(tr("Hide All..."), this, SLOT(issueRemoveFromViewAll())); - } - if (hidden) { - menu.addSeparator(); - menu.addAction(tr("Un-Hide All..."), this, SLOT(issueRestoreToViewAll())); - } + if (!hidden) { + menu.addSeparator(); + menu.addAction(tr("Hide Installed..."), this, SLOT(issueRemoveFromViewCompleted())); + menu.addAction(tr("Hide All..."), this, SLOT(issueRemoveFromViewAll())); + } + if (hidden) { + menu.addSeparator(); + menu.addAction(tr("Un-Hide All..."), this, SLOT(issueRestoreToViewAll())); + } menu.exec(mouseEvent->globalPos()); event->accept(); @@ -345,4 +357,3 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem return QItemDelegate::editorEvent(event, model, option, index); } - diff --git a/src/downloadlistwidgetcompact.h b/src/downloadlistwidgetcompact.h index df1a5f58..28a376eb 100644 --- a/src/downloadlistwidgetcompact.h +++ b/src/downloadlistwidgetcompact.h @@ -35,7 +35,7 @@ class DownloadListWidgetCompact; class DownloadListWidgetCompact : public QWidget { Q_OBJECT - + public: explicit DownloadListWidgetCompact(QWidget *parent = 0); ~DownloadListWidgetCompact(); @@ -69,6 +69,7 @@ signals: void cancelDownload(int index); void pauseDownload(int index); void resumeDownload(int index); + void visitOnNexus(int index); protected: @@ -87,7 +88,8 @@ private slots: void issueDelete(); void issueRemoveFromView(); void issueRestoreToView(); - void issueRestoreToViewAll(); + void issueRestoreToViewAll(); + void issueVisitOnNexus(); void issueCancel(); void issuePause(); void issueResume(); @@ -120,4 +122,3 @@ private: }; #endif // DOWNLOADLISTWIDGETCOMPACT_H - diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 93a46d78..0341152a 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -36,6 +36,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include #include @@ -607,7 +608,7 @@ void DownloadManager::removeFile(int index, bool deleteFile) if(!download->m_Hidden) metaSettings.setValue("removed", true); } - + endDisableDirWatcher(); } @@ -651,7 +652,7 @@ void DownloadManager::restoreDownload(int index) index = 0; for (QVector::const_iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter ) { - + if ((*iter)->m_State >= minState) { restoreDownload(index); } @@ -876,6 +877,34 @@ void DownloadManager::queryInfo(int index) setState(info, STATE_FETCHINGMODINFO); } +void DownloadManager::visitOnNexus(int index) +{ + if ((index < 0) || (index >= m_ActiveDownloads.size())) { + reportError(tr("VisitNexus: invalid download index %1").arg(index)); + return; + } + DownloadInfo *info = m_ActiveDownloads[index]; + + if (info->m_FileInfo->repository != "Nexus") { + qWarning("Visiting mod page is currently only possible with Nexus"); + return; + } + + if (info->m_State < DownloadManager::STATE_READY) { + // UI shouldn't allow this + return; + } + int modID = info->m_FileInfo->modID; + + QString gameName = info->m_FileInfo->gameName; + if (modID > 0) { + QDesktopServices::openUrl(QUrl(m_NexusInterface->getModURL(modID, gameName))); + } + else { + emit showMessage(tr("Nexus ID for this Mod is unknown")); + } +} + int DownloadManager::numTotalDownloads() const { @@ -1756,4 +1785,4 @@ void DownloadManager::checkDownloadTimeout() resumeDownload(i); } } -} \ No newline at end of file +} diff --git a/src/downloadmanager.h b/src/downloadmanager.h index aa859b13..24bc6d7f 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -435,6 +435,8 @@ public slots: void queryInfo(int index); + void visitOnNexus(int index); + void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); void nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a428d5b3..7ddd35c5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -254,7 +254,7 @@ MainWindow::MainWindow(QSettings &initSettings actionToToolButton(ui->actionHelp); createHelpWidget(); - + for (QAction *action : ui->toolBar->actions()) { if (action->isSeparator()) { // insert spacers @@ -400,7 +400,7 @@ MainWindow::MainWindow(QSettings &initSettings new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Enter), this, SLOT(openExplorer_activated())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this, SLOT(openExplorer_activated())); - + new QShortcut(QKeySequence::Refresh, this, SLOT(refreshProfile_activated())); @@ -2336,9 +2336,11 @@ void MainWindow::removeMod_clicked() tr("Remove the following mods?
    %1
").arg(mods), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { // use mod names instead of indexes because those become invalid during the removal + DownloadManager::startDisableDirWatcher(); for (QString name : modNames) { m_OrganizerCore.modList()->removeRowForce(ModInfo::getIndex(name), QModelIndex()); } + DownloadManager::endDisableDirWatcher(); } } else { m_OrganizerCore.modList()->removeRow(m_ContextRow, QModelIndex()); @@ -2500,7 +2502,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, connect(&dialog, SIGNAL(modOpenPrev(int)), this, SLOT(modOpenPrev(int)), Qt::QueuedConnection); connect(&dialog, SIGNAL(originModified(int)), this, SLOT(originModified(int))); connect(&dialog, SIGNAL(endorseMod(ModInfo::Ptr)), this, SLOT(endorseMod(ModInfo::Ptr))); - + //Open the tab first if we want to use the standard indexes of the tabs. if (tab != -1) { dialog.openTab(tab); @@ -2687,7 +2689,7 @@ void MainWindow::openExplorer_activated() QModelIndex idx = selection->currentIndex(); QString fileName = idx.data().toString(); - + ModInfo::Ptr modInfo = ModInfo::getByIndex(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName))); std::vector flags = modInfo->getFlags(); @@ -4239,6 +4241,7 @@ void MainWindow::updateDownloadListDelegate() connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), &m_OrganizerCore, SLOT(installDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfo(int))); + connect(ui->downloadView->itemDelegate(), SIGNAL(visitOnNexus(int)), m_OrganizerCore.downloadManager(), SLOT(visitOnNexus(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(removeDownload(int, bool)), m_OrganizerCore.downloadManager(), SLOT(removeDownload(int, bool))); connect(ui->downloadView->itemDelegate(), SIGNAL(restoreDownload(int)), m_OrganizerCore.downloadManager(), SLOT(restoreDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(cancelDownload(int)), m_OrganizerCore.downloadManager(), SLOT(cancelDownload(int))); -- cgit v1.3.1 From 30f170c10d7838a855524c5466eb9d7ea70d34db Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Sat, 16 Jun 2018 23:18:25 -0500 Subject: Extend mod backups and load order backups to a maximum of 10 --- src/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7ddd35c5..fc666a49 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4971,7 +4971,7 @@ bool MainWindow::createBackup(const QString &filePath, const QDateTime &time) QString outPath = filePath + "." + time.toString(PATTERN_BACKUP_DATE); if (shellCopy(QStringList(filePath), QStringList(outPath), this)) { QFileInfo fileInfo(filePath); - removeOldFiles(fileInfo.absolutePath(), fileInfo.fileName() + PATTERN_BACKUP_GLOB, 3, QDir::Name); + removeOldFiles(fileInfo.absolutePath(), fileInfo.fileName() + PATTERN_BACKUP_GLOB, 10, QDir::Name); return true; } else { return false; -- cgit v1.3.1 From 2524d65441e99cbb14037144b8af60e1d25e1179 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Mon, 16 Jul 2018 20:56:47 +0200 Subject: Added "Open in Folder" option to downloads tab. --- src/downloadlistwidget.cpp | 10 +++++++++- src/downloadlistwidget.h | 2 ++ src/downloadlistwidgetcompact.cpp | 9 ++++++++- src/downloadlistwidgetcompact.h | 2 ++ src/downloadmanager.cpp | 25 +++++++++++++++++++++++++ src/downloadmanager.h | 2 ++ src/mainwindow.cpp | 1 + 7 files changed, 49 insertions(+), 2 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/downloadlistwidget.cpp b/src/downloadlistwidget.cpp index 5ab5d397..0ef408fb 100644 --- a/src/downloadlistwidget.cpp +++ b/src/downloadlistwidget.cpp @@ -272,6 +272,10 @@ void DownloadListWidgetDelegate::issueVisitOnNexus() emit visitOnNexus(m_ContextRow); } +void DownloadListWidgetDelegate::issueOpenInDownloadsFolder() +{ + emit openInDownloadsFolder(m_ContextRow); +} void DownloadListWidgetDelegate::issueCancel() { @@ -352,6 +356,8 @@ bool DownloadListWidgetDelegate::editorEvent(QEvent *event, QAbstractItemModel * }else { menu.addAction(tr("Visit on Nexus"), this,SLOT(issueVisitOnNexus())); } + + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); menu.addSeparator(); @@ -364,9 +370,11 @@ bool DownloadListWidgetDelegate::editorEvent(QEvent *event, QAbstractItemModel * } else if (state == DownloadManager::STATE_DOWNLOADING){ menu.addAction(tr("Cancel"), this, SLOT(issueCancel())); menu.addAction(tr("Pause"), this, SLOT(issuePause())); + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); } else if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR) || (state == DownloadManager::STATE_PAUSING)) { - menu.addAction(tr("Remove"), this, SLOT(issueDelete())); + menu.addAction(tr("Delete"), this, SLOT(issueDelete())); menu.addAction(tr("Resume"), this, SLOT(issueResume())); + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); } menu.addSeparator(); diff --git a/src/downloadlistwidget.h b/src/downloadlistwidget.h index e2746f3a..4dcbea99 100644 --- a/src/downloadlistwidget.h +++ b/src/downloadlistwidget.h @@ -72,6 +72,7 @@ signals: void pauseDownload(int index); void resumeDownload(int index); void visitOnNexus(int index); + void openInDownloadsFolder(int index); protected: @@ -92,6 +93,7 @@ private slots: void issueRestoreToView(); void issueRestoreToViewAll(); void issueVisitOnNexus(); + void issueOpenInDownloadsFolder(); void issueCancel(); void issuePause(); void issueResume(); diff --git a/src/downloadlistwidgetcompact.cpp b/src/downloadlistwidgetcompact.cpp index 99cbd7cb..1d1805ef 100644 --- a/src/downloadlistwidgetcompact.cpp +++ b/src/downloadlistwidgetcompact.cpp @@ -226,6 +226,11 @@ void DownloadListWidgetCompactDelegate::issueVisitOnNexus() emit visitOnNexus(m_ContextIndex.row()); } +void DownloadListWidgetCompactDelegate::issueOpenInDownloadsFolder() +{ + emit openInDownloadsFolder(m_ContextIndex.row()); +} + void DownloadListWidgetCompactDelegate::issueRestoreToView() { emit restoreDownload(m_ContextIndex.row()); @@ -317,6 +322,7 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem }else { menu.addAction(tr("Visit on Nexus"), this, SLOT(issueVisitOnNexus())); } + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); menu.addSeparator(); menu.addAction(tr("Delete"), this, SLOT(issueDelete())); if (hidden) { @@ -327,11 +333,12 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem } else if (state == DownloadManager::STATE_DOWNLOADING){ menu.addAction(tr("Cancel"), this, SLOT(issueCancel())); menu.addAction(tr("Pause"), this, SLOT(issuePause())); + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); } else if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR) || (state == DownloadManager::STATE_PAUSING)) { menu.addAction(tr("Remove"), this, SLOT(issueDelete())); menu.addAction(tr("Resume"), this, SLOT(issueResume())); + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); } - menu.addSeparator(); } menu.addAction(tr("Delete Installed..."), this, SLOT(issueDeleteCompleted())); diff --git a/src/downloadlistwidgetcompact.h b/src/downloadlistwidgetcompact.h index 28a376eb..c25b7e99 100644 --- a/src/downloadlistwidgetcompact.h +++ b/src/downloadlistwidgetcompact.h @@ -70,6 +70,7 @@ signals: void pauseDownload(int index); void resumeDownload(int index); void visitOnNexus(int index); + void openInDownloadsFolder(int index); protected: @@ -90,6 +91,7 @@ private slots: void issueRestoreToView(); void issueRestoreToViewAll(); void issueVisitOnNexus(); + void issueOpenInDownloadsFolder(); void issueCancel(); void issuePause(); void issueResume(); diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 9761fee4..1a2934a5 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -911,6 +911,31 @@ void DownloadManager::visitOnNexus(int index) } } +void DownloadManager::openInDownloadsFolder(int index) +{ + if ((index < 0) || (index >= m_ActiveDownloads.size())) { + reportError(tr("VisitNexus: invalid download index %1").arg(index)); + return; + } + QString params = "/select,\""; + QDir path = QDir(m_OutputDirectory); + if (path.exists(getFileName(index))) { + params = params + QDir::toNativeSeparators(getFilePath(index)) + "\""; + + ::ShellExecuteW(nullptr, nullptr, L"explorer", ToWString(params).c_str(), nullptr, SW_SHOWNORMAL); + return; + } + else if (path.exists(getFileName(index) + ".unfinished")) { + params = params + QDir::toNativeSeparators(getFilePath(index)+".unfinished") + "\""; + + ::ShellExecuteW(nullptr, nullptr, L"explorer", ToWString(params).c_str(), nullptr, SW_SHOWNORMAL); + return; + } + + ::ShellExecuteW(nullptr, L"explore", ToWString(QDir::toNativeSeparators(m_OutputDirectory)).c_str(), nullptr, nullptr, SW_SHOWNORMAL); + return; +} + int DownloadManager::numTotalDownloads() const { diff --git a/src/downloadmanager.h b/src/downloadmanager.h index fa3764b7..514402ee 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -438,6 +438,8 @@ public slots: void visitOnNexus(int index); + void openInDownloadsFolder(int index); + void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); void nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index fc666a49..436d4d26 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4242,6 +4242,7 @@ void MainWindow::updateDownloadListDelegate() connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), &m_OrganizerCore, SLOT(installDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfo(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(visitOnNexus(int)), m_OrganizerCore.downloadManager(), SLOT(visitOnNexus(int))); + connect(ui->downloadView->itemDelegate(), SIGNAL(openInDownloadsFolder(int)), m_OrganizerCore.downloadManager(), SLOT(openInDownloadsFolder(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(removeDownload(int, bool)), m_OrganizerCore.downloadManager(), SLOT(removeDownload(int, bool))); connect(ui->downloadView->itemDelegate(), SIGNAL(restoreDownload(int)), m_OrganizerCore.downloadManager(), SLOT(restoreDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(cancelDownload(int)), m_OrganizerCore.downloadManager(), SLOT(cancelDownload(int))); -- cgit v1.3.1 From 7f3dc586b0422a31d34d00fcf23b2f2922418650 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 11 Jul 2018 05:45:58 -0500 Subject: Redirect endorsements of MO2 to the Skyrim SE nexus --- src/mainwindow.cpp | 17 ++++++++++++----- src/modinfo.cpp | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 436d4d26..01f37d75 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4204,12 +4204,16 @@ void MainWindow::on_actionUpdate_triggered() void MainWindow::on_actionEndorseMO_triggered() { + // Normally this would be the managed game but MO2 is only uploaded to the Skyrim SE site right now + IPluginGame * game = m_OrganizerCore.getGame("skyrimse"); + if (!game) return; + if (QMessageBox::question(this, tr("Endorse Mod Organizer"), tr("Do you want to endorse Mod Organizer on %1 now?").arg( - NexusInterface::instance(&m_PluginContainer)->getGameURL(m_OrganizerCore.managedGame()->gameShortName())), + NexusInterface::instance(&m_PluginContainer)->getGameURL(game->gameShortName())), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { NexusInterface::instance(&m_PluginContainer)->requestToggleEndorsement( - m_OrganizerCore.managedGame()->gameShortName(), m_OrganizerCore.managedGame()->nexusModOrganizerID(), true, this, QVariant(), QString()); + game->gameShortName(), game->nexusModOrganizerID(), true, this, QVariant(), QString()); } } @@ -4274,8 +4278,11 @@ void MainWindow::nxmUpdatesAvailable(const std::vector &modIDs, QVariant us QVariantList resultList = resultData.toList(); for (auto iter = resultList.begin(); iter != resultList.end(); ++iter) { QVariantMap result = iter->toMap(); - if (result["id"].toInt() == m_OrganizerCore.managedGame()->nexusModOrganizerID() - && result["game_id"].toInt() == m_OrganizerCore.managedGame()->nexusGameID()) { + // Normally this would be the managed game but MO2 is only uploaded to the Skyrim SE site right now + IPluginGame * game = m_OrganizerCore.getGame("skyrimse"); + if (game + && result["id"].toInt() == game->nexusModOrganizerID() + && result["game_id"].toInt() == game->nexusGameID()) { if (!result["voted_by_user"].toBool()) { ui->actionEndorseMO->setVisible(true); } @@ -4326,7 +4333,7 @@ void MainWindow::nxmEndorsementToggled(QString, int, QVariant, QVariant resultDa { if (resultData.toBool()) { ui->actionEndorseMO->setVisible(false); - QMessageBox::question(this, tr("Thank you!"), tr("Thank you for your endorsement!")); + QMessageBox::information(this, tr("Thank you!"), tr("Thank you for your endorsement!")); } if (!disconnect(sender(), SIGNAL(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)), diff --git a/src/modinfo.cpp b/src/modinfo.cpp index bd4c1254..1f2520c9 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -286,9 +286,9 @@ int ModInfo::checkAllForUpdate(PluginContainer *pluginContainer, QObject *receiv int result = 0; std::vector modIDs; - //I ought to store this, it's used elsewhere - IPluginGame const *game = qApp->property("managed_game").value(); - if (game->nexusModOrganizerID()) { + // Normally this would be the managed game but MO2 is only uploaded to the Skyrim SE site right now + IPluginGame const *game = pluginContainer->managedGame("Skyrim Special Edition"); + if (game && game->nexusModOrganizerID()) { modIDs.push_back(game->nexusModOrganizerID()); checkChunkForUpdate(pluginContainer, modIDs, receiver, game->gameShortName()); modIDs.clear(); -- cgit v1.3.1 From f20a1f6a849510438ca5c9abe8fdac1dada263d2 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 16 Jul 2018 15:22:51 -0500 Subject: Allow "ignore missing data" to work with multiple mods --- src/mainwindow.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 01f37d75..1f5cef2f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2619,12 +2619,25 @@ void MainWindow::displayModInformation(int row, int tab) void MainWindow::ignoreMissingData_clicked() { - ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); - QDir(info->absolutePath()).mkdir("textures"); - info->testValid(); - connect(this, SIGNAL(modListDataChanged(QModelIndex,QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex,QModelIndex))); + QItemSelectionModel *selection = ui->modList->selectionModel(); + if (selection->hasSelection() && selection->selectedRows().count() > 1) { + for (QModelIndex idx : selection->selectedRows()) { + int row_idx = idx.data(Qt::UserRole + 1).toInt(); + ModInfo::Ptr info = ModInfo::getByIndex(row_idx); + QDir(info->absolutePath()).mkdir("textures"); + info->testValid(); + connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex))); - emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1)); + emit modListDataChanged(m_OrganizerCore.modList()->index(row_idx, 0), m_OrganizerCore.modList()->index(row_idx, m_OrganizerCore.modList()->columnCount() - 1)); + } + } else { + ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); + QDir(info->absolutePath()).mkdir("textures"); + info->testValid(); + connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex))); + + emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1)); + } } void MainWindow::markConverted_clicked() -- cgit v1.3.1 From b4530eb84321f684e0ad764ed3cdafbbd9e4315c Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 16 Jul 2018 15:31:08 -0500 Subject: Allow "mark as converted" to work with multiple mods --- src/mainwindow.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1f5cef2f..5041f661 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2642,10 +2642,21 @@ void MainWindow::ignoreMissingData_clicked() void MainWindow::markConverted_clicked() { - ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); - info->markConverted(true); - connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex))); - emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1)); + QItemSelectionModel *selection = ui->modList->selectionModel(); + if (selection->hasSelection() && selection->selectedRows().count() > 1) { + for (QModelIndex idx : selection->selectedRows()) { + int row_idx = idx.data(Qt::UserRole + 1).toInt(); + ModInfo::Ptr info = ModInfo::getByIndex(row_idx); + info->markConverted(true); + connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex))); + emit modListDataChanged(m_OrganizerCore.modList()->index(row_idx, 0), m_OrganizerCore.modList()->index(row_idx, m_OrganizerCore.modList()->columnCount() - 1)); + } + } else { + ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); + info->markConverted(true); + connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex))); + emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1)); + } } -- cgit v1.3.1 From 952f1fe8cd6dda5f97fd29fce9e7e8372093c3f4 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 16 Jul 2018 15:35:11 -0500 Subject: Allow "open in explorer" to work with multiple mods --- src/mainwindow.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5041f661..dc4ede28 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2683,9 +2683,17 @@ void MainWindow::visitWebPage_clicked() void MainWindow::openExplorer_clicked() { - ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow); - - ::ShellExecuteW(nullptr, L"explore", ToWString(modInfo->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); + QItemSelectionModel *selection = ui->modList->selectionModel(); + if (selection->hasSelection() && selection->selectedRows().count() > 1) { + for (QModelIndex idx : selection->selectedRows()) { + ModInfo::Ptr info = ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt()); + ::ShellExecuteW(nullptr, L"explore", ToWString(info->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); + } + } + else { + ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow); + ::ShellExecuteW(nullptr, L"explore", ToWString(modInfo->absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); + } } void MainWindow::openExplorer_activated() -- cgit v1.3.1 From eaf3655492e34a5b613a3f75576c872f8f932d17 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 16 Jul 2018 15:35:41 -0500 Subject: Allow "ignore update" to work with multiple mods --- src/mainwindow.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index dc4ede28..19f61ae8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3108,8 +3108,17 @@ void MainWindow::changeVersioningScheme() { } void MainWindow::ignoreUpdate() { - ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); - info->ignoreUpdate(true); + QItemSelectionModel *selection = ui->modList->selectionModel(); + if (selection->hasSelection() && selection->selectedRows().count() > 1) { + for (QModelIndex idx : selection->selectedRows()) { + ModInfo::Ptr info = ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt()); + info->ignoreUpdate(true); + } + } + else { + ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); + info->ignoreUpdate(true); + } } void MainWindow::unignoreUpdate() -- cgit v1.3.1 From a830f3e09efe60d10dc7d97fa645a164f54994a0 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Mon, 16 Jul 2018 15:36:06 -0500 Subject: Allow "unignore update" to work with multiple mods --- src/mainwindow.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 19f61ae8..f70e66a6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3123,8 +3123,17 @@ void MainWindow::ignoreUpdate() { void MainWindow::unignoreUpdate() { - ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); - info->ignoreUpdate(false); + QItemSelectionModel *selection = ui->modList->selectionModel(); + if (selection->hasSelection() && selection->selectedRows().count() > 1) { + for (QModelIndex idx : selection->selectedRows()) { + ModInfo::Ptr info = ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt()); + info->ignoreUpdate(false); + } + } + else { + ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); + info->ignoreUpdate(false); + } } void MainWindow::addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, -- cgit v1.3.1 From 75478f68a12c89af790ba2aae127d4834c6d44a5 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Tue, 17 Jul 2018 13:32:53 +0200 Subject: Avoid asking users if they are sure they want to close of all downlaods are paused. --- src/downloadmanager.cpp | 10 ++++++++++ src/downloadmanager.h | 7 +++++++ src/mainwindow.cpp | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src/mainwindow.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 385d2246..beb498c1 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -230,6 +230,16 @@ bool DownloadManager::downloadsInProgress() return false; } +bool DownloadManager::downloadsInProgressNoPause() +{ + for (QVector::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter) { + if ((*iter)->m_State < STATE_READY && (*iter)->m_State != STATE_PAUSED) { + return true; + } + } + return false; +} + void DownloadManager::pauseAll() { diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 514402ee..136ecf2a 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -138,6 +138,13 @@ public: **/ bool downloadsInProgress(); + /** + * @brief determine if a download is currently in progress, does not count paused ones. + * + * @return true if there is currently a download in progress (that is not paused already). + **/ + bool downloadsInProgressNoPause(); + /** * @brief set the output directory to write to * diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f70e66a6..5999608c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -883,7 +883,7 @@ void MainWindow::closeEvent(QCloseEvent* event) { m_closing = true; - if (m_OrganizerCore.downloadManager()->downloadsInProgress()) { + if (m_OrganizerCore.downloadManager()->downloadsInProgressNoPause()) { 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) { -- cgit v1.3.1 From 023cacab7fc2a9c36749fe235255fce8c4edd65b Mon Sep 17 00:00:00 2001 From: Al12rs Date: Tue, 17 Jul 2018 16:26:17 +0200 Subject: Added ability to open mod information window by double cliking on plugins. --- src/mainwindow.cpp | 38 ++++++++++++++++++ src/mainwindow.h | 1 + src/mainwindow.ui | 115 +++++++++++++++++------------------------------------ src/pluginlist.cpp | 7 ++++ src/pluginlist.h | 6 +++ 5 files changed, 88 insertions(+), 79 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5999608c..c4e888ac 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2872,6 +2872,44 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index) } } +void MainWindow::on_espList_doubleClicked(const QModelIndex &index) +{ + if (!index.isValid()) { + return; + } + + if (m_OrganizerCore.pluginList()->timeElapsedSinceLastChecked() <= QApplication::doubleClickInterval()) { + // don't interpret double click if we only just checked a plugin + return; + } + + QModelIndex sourceIdx = mapToModel(m_OrganizerCore.pluginList(), index); + if (!sourceIdx.isValid()) { + return; + } + try { + + QItemSelectionModel *selection = ui->espList->selectionModel(); + + if (selection->hasSelection() && selection->selectedRows().count() == 1) { + + QModelIndex idx = selection->currentIndex(); + QString fileName = idx.data().toString(); + + + displayModInformation(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName))); + // workaround to cancel the editor that might have opened because of + // selection-click + ui->espList->closePersistentEditor(index); + + + } + } + catch (const std::exception &e) { + reportError(e.what()); + } +} + bool MainWindow::populateMenuCategories(QMenu *menu, int targetID) { ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow); diff --git a/src/mainwindow.h b/src/mainwindow.h index 737a1534..773bf298 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -574,6 +574,7 @@ private slots: // ui slots void on_executablesListBox_currentIndexChanged(int index); void on_modList_customContextMenuRequested(const QPoint &pos); void on_modList_doubleClicked(const QModelIndex &index); + void on_espList_doubleClicked(const QModelIndex &index); void on_profileBox_currentIndexChanged(int index); void on_savegameList_customContextMenuRequested(const QPoint &pos); void on_startButton_clicked(); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index e0aa6f36..d8873d4f 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -96,9 +96,9 @@ - - false - + + false + 0 @@ -194,7 +194,7 @@ - + Pick a module collection @@ -248,7 +248,7 @@ p, li { white-space: pre-wrap; } 16 - + @@ -265,16 +265,6 @@ p, li { white-space: pre-wrap; } - - - - - - - - - - Restore Backup... @@ -509,7 +499,7 @@ p, li { white-space: pre-wrap; } - + Qt::Horizontal @@ -521,7 +511,7 @@ p, li { white-space: pre-wrap; } - + @@ -536,12 +526,12 @@ p, li { white-space: pre-wrap; } 22 - + 95 0 - + false @@ -567,7 +557,7 @@ p, li { white-space: pre-wrap; } - + Qt::Horizontal @@ -579,14 +569,14 @@ p, li { white-space: pre-wrap; } - - - + + + 220 0 - + Qt::ClickFocus @@ -608,13 +598,13 @@ p, li { white-space: pre-wrap; } - - + + 220 0 - + Namefilter @@ -835,12 +825,12 @@ p, li { white-space: pre-wrap; } - - true - + + true + Sort - + :/MO/gui/sort:/MO/gui/sort @@ -954,6 +944,9 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps, esms, and esls contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html> + + QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + true @@ -987,6 +980,9 @@ p, li { white-space: pre-wrap; } true + + false + false @@ -1009,15 +1005,12 @@ p, li { white-space: pre-wrap; } - - - + + false + Archives - - true - 6 @@ -1032,17 +1025,7 @@ p, li { white-space: pre-wrap; } 6 - - - - - - - - - - - + @@ -1072,50 +1055,24 @@ p, li { white-space: pre-wrap; } BSAs checked here are loaded in such a way that your installation order is obeyed properly. - - QAbstractItemView::NoEditTriggers - false - + false - + false - - QAbstractItemView::NoDragDrop - - - Qt::IgnoreAction - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - + 20 - + true - + 1 - - false - - - 200 - - - - File - - diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 9153df72..c6cea045 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -77,6 +77,7 @@ PluginList::PluginList(QObject *parent) , m_FontMetrics(QFont()) { connect(this, SIGNAL(writePluginsList()), this, SLOT(generatePluginIndexes())); + m_LastCheck.start(); } PluginList::~PluginList() @@ -583,6 +584,11 @@ void PluginList::disconnectSlots() { m_PluginStateChanged.disconnect_all_slots(); } +int PluginList::timeElapsedSinceLastChecked() const +{ + return m_LastCheck.elapsed(); +} + QStringList PluginList::pluginNames() const { QStringList result; @@ -954,6 +960,7 @@ bool PluginList::setData(const QModelIndex &modIndex, const QVariant &value, int if (role == Qt::CheckStateRole) { m_ESPs[modIndex.row()].m_Enabled = value.toInt() == Qt::Checked || m_ESPs[modIndex.row()].m_ForceEnabled; + m_LastCheck.restart(); emit dataChanged(modIndex, modIndex); refreshLoadOrder(); diff --git a/src/pluginlist.h b/src/pluginlist.h index 583c7272..b8e35c32 100644 --- a/src/pluginlist.h +++ b/src/pluginlist.h @@ -28,6 +28,7 @@ namespace MOBase { class IPluginGame; } #include #include #include +#include #include #pragma warning(push) @@ -192,6 +193,8 @@ public: */ int enabledCount() const; + int timeElapsedSinceLastChecked() const; + QString getName(int index) const { return m_ESPs.at(index).m_Name; } int getPriority(int index) const { return m_ESPs.at(index).m_Priority; } QString getIndexPriority(int index) const; @@ -273,6 +276,7 @@ signals: void writePluginsList(); + private: struct ESPInfo { @@ -347,6 +351,8 @@ private: QTemporaryFile m_TempFile; + QTime m_LastCheck; + const MOBase::IPluginGame *m_GamePlugin; }; -- cgit v1.3.1 From ce2494ba200a6da56634aa3e6cdb6e22884a56e6 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Wed, 18 Jul 2018 12:03:02 +0200 Subject: Don't show info dialog for unmanaged pluugins. --- src/mainwindow.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c4e888ac..2e14a201 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2896,13 +2896,20 @@ void MainWindow::on_espList_doubleClicked(const QModelIndex &index) QModelIndex idx = selection->currentIndex(); QString fileName = idx.data().toString(); + if (ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName)) == UINT_MAX) + return; + + ModInfo::Ptr modInfo = ModInfo::getByIndex(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName))); + std::vector flags = modInfo->getFlags(); - displayModInformation(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName))); - // workaround to cancel the editor that might have opened because of - // selection-click - ui->espList->closePersistentEditor(index); - + if (modInfo->isRegular() || (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end())) { + displayModInformation(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName))); + // workaround to cancel the editor that might have opened because of + // selection-click + ui->espList->closePersistentEditor(index); + + } } } catch (const std::exception &e) { -- cgit v1.3.1 From 8f28e0af36d6246f1230a8aa296cfd5485b34242 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Sat, 21 Jul 2018 20:01:40 +0200 Subject: Temporarely disable the BSA list refresh if it is hidden from view. this will need to be reversted once the Bsa changes are added I presume. --- src/mainwindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2e14a201..f2a17c17 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2544,7 +2544,10 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, , modInfo->stealFiles() , modInfo->archives()); DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure()); - m_OrganizerCore.refreshLists(); + //TODO: change this to always work once the BSA parsing is back in place. + if (ui->bsaList->isVisible()) + m_OrganizerCore.refreshBSAList(); + m_OrganizerCore.refreshESPList(); } } } -- cgit v1.3.1 From cc63717060229ce40279f4ac1edd0907110fee87 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Sat, 21 Jul 2018 20:09:25 +0200 Subject: Added "Open Mods folder" to "Open Folder" context menu. --- src/mainwindow.cpp | 7 +++++++ src/mainwindow.h | 1 + 2 files changed, 8 insertions(+) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f2a17c17..17db79d6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3272,6 +3272,11 @@ void MainWindow::openDownloadsFolder() ::ShellExecuteW(nullptr, L"explore", ToWString(m_OrganizerCore.settings().getDownloadDirectory()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); } +void MainWindow::openModsFolder() +{ + ::ShellExecuteW(nullptr, L"explore", ToWString(m_OrganizerCore.settings().getModDirectory()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); +} + void MainWindow::openGameFolder() { ::ShellExecuteW(nullptr, L"explore", ToWString(m_OrganizerCore.managedGame()->gameDirectory().absolutePath()).c_str(), nullptr, nullptr, SW_SHOWNORMAL); @@ -3465,6 +3470,8 @@ QMenu *MainWindow::openFolderMenu() FolderMenu->addAction(tr("Open Instance folder"), this, SLOT(openInstanceFolder())); + FolderMenu->addAction(tr("Open Mods folder"), this, SLOT(openModsFolder())); + FolderMenu->addAction(tr("Open Profile folder"), this, SLOT(openProfileFolder())); FolderMenu->addAction(tr("Open Downloads folder"), this, SLOT(openDownloadsFolder())); diff --git a/src/mainwindow.h b/src/mainwindow.h index 773bf298..6cf83301 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -502,6 +502,7 @@ private slots: void openInstallFolder(); void openPluginsFolder(); void openDownloadsFolder(); + void openModsFolder(); void openProfileFolder(); void openGameFolder(); void openMyGamesFolder(); -- cgit v1.3.1 From d02df7e4b4d6b539ed744135eee565530c24f006 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Sat, 21 Jul 2018 23:43:04 +0200 Subject: Avoided downloads defaulting to "File Time" sorting at each startup. Improved downloads tab header sizes and resize policy. --- src/mainwindow.cpp | 4 ++-- src/mainwindow.ui | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 17db79d6..c9874b20 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4345,8 +4345,8 @@ void MainWindow::updateDownloadListDelegate() connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(downloadFilterChanged(QString))); ui->downloadView->setModel(sortProxy); - ui->downloadView->sortByColumn(1, Qt::DescendingOrder); - ui->downloadView->header()->resizeSections(QHeaderView::Fixed); + //ui->downloadView->sortByColumn(1, Qt::DescendingOrder); + ui->downloadView->header()->resizeSections(QHeaderView::Stretch); connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), &m_OrganizerCore, SLOT(installDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfo(int))); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index d8873d4f..8de34485 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1243,7 +1243,7 @@ p, li { white-space: pre-wrap; } Qt::ScrollBarAlwaysOn - Qt::ScrollBarAlwaysOff + Qt::ScrollBarAsNeeded true @@ -1276,7 +1276,10 @@ p, li { white-space: pre-wrap; } true - 100 + 50 + + + 15 true -- cgit v1.3.1 From fc8a6b358fb7bda18979c7c5c23c13d7c2ae8dc8 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 20 Jul 2018 03:21:30 -0500 Subject: Improve robustness of endorsement checks At times, the voted_by_user item is returned as Invalid. toBool() causes this to be false, meaning the item is seen as not endorsed. Now, the endorsement state is not checked if the data is invalid. --- src/mainwindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c9874b20..d8dd6e45 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4388,7 +4388,8 @@ void MainWindow::nxmUpdatesAvailable(const std::vector &modIDs, QVariant us if (game && result["id"].toInt() == game->nexusModOrganizerID() && result["game_id"].toInt() == game->nexusGameID()) { - if (!result["voted_by_user"].toBool()) { + if (result["voted_by_user"].type() != QVariant::Invalid && + !result["voted_by_user"].toBool()) { ui->actionEndorseMO->setVisible(true); } } else { @@ -4412,7 +4413,8 @@ void MainWindow::nxmUpdatesAvailable(const std::vector &modIDs, QVariant us (*iter)->setNewestVersion(result["version"].toString()); (*iter)->setNexusDescription(result["description"].toString()); if (NexusInterface::instance(&m_PluginContainer)->getAccessManager()->loggedIn() && - result.contains("voted_by_user")) { + result.contains("voted_by_user") && + result["voted_by_user"].type() != QVariant::Invalid) { // 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()); } -- cgit v1.3.1 From 10be66a62a6d719355d6a494d365e4ea4dac1e9e Mon Sep 17 00:00:00 2001 From: Al12rs Date: Wed, 1 Aug 2018 17:07:35 +0200 Subject: Revert "Temporarely disable the BSA list refresh if it is hidden from view. this will need to be reversted once the Bsa changes are added I presume." This reverts commit 8f28e0af36d6246f1230a8aa296cfd5485b34242. --- src/mainwindow.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d8dd6e45..f587cc50 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2544,10 +2544,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, , modInfo->stealFiles() , modInfo->archives()); DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure()); - //TODO: change this to always work once the BSA parsing is back in place. - if (ui->bsaList->isVisible()) - m_OrganizerCore.refreshBSAList(); - m_OrganizerCore.refreshESPList(); + m_OrganizerCore.refreshLists(); } } } -- cgit v1.3.1 From 696bb3bc47daf7779a0520dba64affaac3a5b4ad Mon Sep 17 00:00:00 2001 From: Al12rs Date: Wed, 1 Aug 2018 17:18:07 +0200 Subject: Added CTRL+Double Click on Modlist to open in Explorer --- src/mainwindow.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f587cc50..d3e3c613 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2861,14 +2861,30 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index) return; } - try { - m_ContextRow = m_ModListSortProxy->mapToSource(index).row(); - displayModInformation(sourceIdx.row()); - // workaround to cancel the editor that might have opened because of - // selection-click - ui->modList->closePersistentEditor(index); - } catch (const std::exception &e) { - reportError(e.what()); + Qt::KeyboardModifiers modifiers = QApplication::queryKeyboardModifiers(); + if (modifiers.testFlag(Qt::ControlModifier)) { + try { + m_ContextRow = m_ModListSortProxy->mapToSource(index).row(); + openExplorer_clicked(); + // workaround to cancel the editor that might have opened because of + // selection-click + ui->modList->closePersistentEditor(index); + } + catch (const std::exception &e) { + reportError(e.what()); + } + } + else { + try { + m_ContextRow = m_ModListSortProxy->mapToSource(index).row(); + displayModInformation(sourceIdx.row()); + // workaround to cancel the editor that might have opened because of + // selection-click + ui->modList->closePersistentEditor(index); + } + catch (const std::exception &e) { + reportError(e.what()); + } } } -- cgit v1.3.1 From e1e367c7eae67471e760673a8149ccf30bac8685 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Wed, 1 Aug 2018 17:55:07 +0200 Subject: Added CTRL+Doubleclick on plugin list as well --- src/mainwindow.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d3e3c613..f6cfbfbd 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2920,11 +2920,20 @@ void MainWindow::on_espList_doubleClicked(const QModelIndex &index) if (modInfo->isRegular() || (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end())) { - displayModInformation(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName))); - // workaround to cancel the editor that might have opened because of - // selection-click - ui->espList->closePersistentEditor(index); + Qt::KeyboardModifiers modifiers = QApplication::queryKeyboardModifiers(); + if (modifiers.testFlag(Qt::ControlModifier)) { + openExplorer_activated(); + // workaround to cancel the editor that might have opened because of + // selection-click + ui->espList->closePersistentEditor(index); + } + else { + displayModInformation(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName))); + // workaround to cancel the editor that might have opened because of + // selection-click + ui->espList->closePersistentEditor(index); + } } } } -- cgit v1.3.1