From 2b2bb69351328a93a29ae084d6391ffa347be47f Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 26 Dec 2020 19:14:34 -0500 Subject: don't update mods after installing in offline mode --- src/mainwindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a270fd10..8d9857c1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -5432,6 +5432,10 @@ void MainWindow::updateDownloadView() void MainWindow::modUpdateCheck(std::multimap IDs) { + if (m_OrganizerCore.settings().network().offlineMode()) { + return; + } + if (NexusInterface::instance().getAccessManager()->validated()) { ModInfo::manualUpdateCheck(this, IDs); } else { -- cgit v1.3.1 From 3eb64c32e8643a34ce2de07bdb0f2fae2869b69a Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 26 Dec 2020 19:51:47 -0500 Subject: split downloads tab --- src/CMakeLists.txt | 1 + src/datatab.h | 5 +++ src/downloadstab.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ src/downloadstab.h | 34 +++++++++++++++++++ src/mainwindow.cpp | 94 ++++++++-------------------------------------------- src/mainwindow.h | 8 ++--- 6 files changed, 143 insertions(+), 87 deletions(-) create mode 100644 src/downloadstab.cpp create mode 100644 src/downloadstab.h (limited to 'src/mainwindow.cpp') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 117528f8..fdbe8e38 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,6 +99,7 @@ add_filter(NAME src/loot GROUPS add_filter(NAME src/mainwindow GROUPS datatab + downloadstab iconfetcher filetree filetreeitem diff --git a/src/datatab.h b/src/datatab.h index a0f29a5f..32d788f6 100644 --- a/src/datatab.h +++ b/src/datatab.h @@ -1,3 +1,6 @@ +#ifndef MODORGANIZER_DATATAB_INCLUDED +#define MODORGANIZER_DATATAB_INCLUDED + #include "modinfodialogfwd.h" #include "modinfo.h" #include @@ -58,3 +61,5 @@ private: void updateOptions(); void ensureFullyLoaded(); }; + +#endif // MODORGANIZER_DATATAB_INCLUDED diff --git a/src/downloadstab.cpp b/src/downloadstab.cpp new file mode 100644 index 00000000..a1a5a474 --- /dev/null +++ b/src/downloadstab.cpp @@ -0,0 +1,88 @@ +#include "downloadstab.h" +#include "downloadlist.h" +#include "downloadlistsortproxy.h" +#include "downloadlistwidget.h" +#include "organizercore.h" +#include "ui_mainwindow.h" + +DownloadsTab::DownloadsTab(OrganizerCore& core, Ui::MainWindow* mwui) + : m_core(core), ui{ + mwui->btnRefreshDownloads, mwui->downloadView, mwui->showHiddenBox, + mwui->downloadFilterEdit} +{ + DownloadList *sourceModel = new DownloadList( + m_core.downloadManager(), ui.list); + + DownloadListSortProxy *sortProxy = new DownloadListSortProxy( + m_core.downloadManager(), ui.list); + + sortProxy->setSourceModel(sourceModel); + connect(ui.filter, SIGNAL(textChanged(QString)), sortProxy, SLOT(updateFilter(QString))); + connect(ui.filter, SIGNAL(textChanged(QString)), this, SLOT(downloadFilterChanged(QString))); + + ui.list->setSourceModel(sourceModel); + ui.list->setModel(sortProxy); + ui.list->setManager(m_core.downloadManager()); + ui.list->setItemDelegate(new DownloadProgressDelegate( + m_core.downloadManager(), sortProxy, ui.list)); + update(); + + connect(ui.refresh, &QPushButton::clicked, [&]{ refresh(); }); + connect(ui.list, SIGNAL(installDownload(int)), &m_core, SLOT(installDownload(int))); + connect(ui.list, SIGNAL(queryInfo(int)), m_core.downloadManager(), SLOT(queryInfo(int))); + connect(ui.list, SIGNAL(queryInfoMd5(int)), m_core.downloadManager(), SLOT(queryInfoMd5(int))); + connect(ui.list, SIGNAL(visitOnNexus(int)), m_core.downloadManager(), SLOT(visitOnNexus(int))); + connect(ui.list, SIGNAL(openFile(int)), m_core.downloadManager(), SLOT(openFile(int))); + connect(ui.list, SIGNAL(openMetaFile(int)), m_core.downloadManager(), SLOT(openMetaFile(int))); + connect(ui.list, SIGNAL(openInDownloadsFolder(int)), m_core.downloadManager(), SLOT(openInDownloadsFolder(int))); + connect(ui.list, SIGNAL(removeDownload(int, bool)), m_core.downloadManager(), SLOT(removeDownload(int, bool))); + connect(ui.list, SIGNAL(restoreDownload(int)), m_core.downloadManager(), SLOT(restoreDownload(int))); + connect(ui.list, SIGNAL(cancelDownload(int)), m_core.downloadManager(), SLOT(cancelDownload(int))); + connect(ui.list, SIGNAL(pauseDownload(int)), m_core.downloadManager(), SLOT(pauseDownload(int))); + connect(ui.list, SIGNAL(resumeDownload(int)), this, SLOT(resumeDownload(int))); +} + +void DownloadsTab::update() +{ + // this means downloadTab initialization hasn't happened yet + if (ui.list->model() == nullptr) { + return; + } + + // set the view attribute and default row sizes + if (m_core.settings().interface().compactDownloads()) { + ui.list->setProperty("downloadView", "compact"); + ui.list->setStyleSheet("DownloadListWidget::item { padding: 4px 2px; }"); + } else { + ui.list->setProperty("downloadView", "standard"); + ui.list->setStyleSheet("DownloadListWidget::item { padding: 16px 4px; }"); + } + + ui.list->setMetaDisplay(m_core.settings().interface().metaDownloads()); + ui.list->style()->unpolish(ui.list); + ui.list->style()->polish(ui.list); + qobject_cast(ui.list->header())->customResizeSections(); + + m_core.downloadManager()->refreshList(); +} + +void DownloadsTab::refresh() +{ + m_core.downloadManager()->refreshList(); +} + +void DownloadsTab::resumeDownload(int downloadIndex) +{ + m_core.loggedInAction(ui.list, [this, downloadIndex] { + m_core.downloadManager()->resumeDownload(downloadIndex); + }); +} + +void DownloadsTab::downloadFilterChanged(const QString &filter) +{ + if (!filter.isEmpty()) { + ui.list->setStyleSheet("QTreeView { border: 2px ridge #f00; }"); + } else { + ui.list->setStyleSheet(""); + } +} diff --git a/src/downloadstab.h b/src/downloadstab.h new file mode 100644 index 00000000..3ccdf5f4 --- /dev/null +++ b/src/downloadstab.h @@ -0,0 +1,34 @@ +#ifndef MODORGANIZER_DOWNLOADTAB_INCLUDED +#define MODORGANIZER_DOWNLOADTAB_INCLUDED + +namespace Ui { class MainWindow; } +class OrganizerCore; +class DownloadListWidget; + +class DownloadsTab : public QObject +{ + Q_OBJECT; + +public: + DownloadsTab(OrganizerCore& core, Ui::MainWindow* ui); + + void update(); + +private: + struct DownloadsTabUi + { + QPushButton* refresh; + DownloadListWidget* list; + QCheckBox* showHidden; + QLineEdit* filter; + }; + + OrganizerCore& m_core; + DownloadsTabUi ui; + + void refresh(); + void downloadFilterChanged(const QString &filter); + void resumeDownload(int downloadIndex); +}; + +#endif // MODORGANIZER_DOWNLOADTAB_INCLUDED diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8d9857c1..8777c4ac 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -76,6 +76,7 @@ along with Mod Organizer. If not, see . #include "statusbar.h" #include "filterlist.h" #include "datatab.h" +#include "downloadstab.h" #include "instancemanagerdialog.h" #include #include @@ -347,11 +348,11 @@ MainWindow::MainWindow(Settings &settings ui->bsaList->setLocalMoveOnly(true); ui->bsaList->setHeaderHidden(true); - initDownloadView(); - const bool pluginListAdjusted = settings.geometry().restoreState(ui->espList->header()); + + // data tab m_DataTab.reset(new DataTab(m_OrganizerCore, m_PluginContainer, this, ui)); m_DataTab->restoreState(settings); @@ -365,6 +366,11 @@ MainWindow::MainWindow(Settings &settings m_DataTab.get(), &DataTab::displayModInformation, [&](auto&& m, auto&& i, auto&& tab){ displayModInformation(m, i, tab); }); + + // downloads tab + m_DownloadsTab.reset(new DownloadsTab(m_OrganizerCore, ui)); + + // Hide stuff we do not need: IPluginGame const* game = m_OrganizerCore.managedGame(); if (!game->feature()) { @@ -1265,15 +1271,6 @@ void MainWindow::espFilterChanged(const QString &filter) updatePluginCount(); } -void MainWindow::downloadFilterChanged(const QString &filter) -{ - if (!filter.isEmpty()) { - ui->downloadView->setStyleSheet("QTreeView { border: 2px ridge #f00; }"); - } else { - ui->downloadView->setStyleSheet(""); - } -} - void MainWindow::expandModList(const QModelIndex &index) { QAbstractItemModel *model = ui->modList->model(); @@ -2310,11 +2307,6 @@ QMainWindow* MainWindow::mainWindow() return this; } -void MainWindow::on_btnRefreshDownloads_clicked() -{ - m_OrganizerCore.downloadManager()->refreshList(); -} - void MainWindow::on_tabWidget_currentChanged(int index) { QWidget* currentWidget = ui->tabWidget->widget(index); @@ -2856,13 +2848,6 @@ void MainWindow::backupMod_clicked() m_OrganizerCore.refresh(); } -void MainWindow::resumeDownload(int downloadIndex) -{ - m_OrganizerCore.loggedInAction(this, [this, downloadIndex] { - m_OrganizerCore.downloadManager()->resumeDownload(downloadIndex); - }); -} - void MainWindow::endorseMod(ModInfo::Ptr mod) { @@ -5161,7 +5146,7 @@ void MainWindow::on_actionSettings_triggered() } ui->statusBar->checkSettings(m_OrganizerCore.settings()); - updateDownloadView(); + m_DownloadsTab->update(); m_OrganizerCore.setLogLevel(settings.diagnostics().logLevel()); @@ -5184,7 +5169,7 @@ void MainWindow::onPluginRegistrationChanged() { updateModPageMenu(); scheduleCheckForProblems(); - updateDownloadView(); + m_DownloadsTab->update(); } void MainWindow::on_actionNexus_triggered() @@ -5240,7 +5225,9 @@ void MainWindow::languageChange(const QString &newLanguage) createHelpMenu(); - updateDownloadView(); + if (m_DownloadsTab) { + m_DownloadsTab->update(); + } QMenu *listOptionsMenu = new QMenu(ui->listOptionsBtn); initModListContextMenu(listOptionsMenu); @@ -5375,61 +5362,6 @@ void MainWindow::actionWontEndorseMO() } } -void MainWindow::initDownloadView() -{ - DownloadList *sourceModel = new DownloadList(m_OrganizerCore.downloadManager(), ui->downloadView); - DownloadListSortProxy *sortProxy = new DownloadListSortProxy(m_OrganizerCore.downloadManager(), ui->downloadView); - sortProxy->setSourceModel(sourceModel); - connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), sortProxy, SLOT(updateFilter(QString))); - connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(downloadFilterChanged(QString))); - - ui->downloadView->setSourceModel(sourceModel); - ui->downloadView->setModel(sortProxy); - ui->downloadView->setManager(m_OrganizerCore.downloadManager()); - ui->downloadView->setItemDelegate(new DownloadProgressDelegate(m_OrganizerCore.downloadManager(), sortProxy, ui->downloadView)); - updateDownloadView(); - - connect(ui->downloadView, SIGNAL(installDownload(int)), &m_OrganizerCore, SLOT(installDownload(int))); - connect(ui->downloadView, SIGNAL(queryInfo(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfo(int))); - connect(ui->downloadView, SIGNAL(queryInfoMd5(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfoMd5(int))); - connect(ui->downloadView, SIGNAL(visitOnNexus(int)), m_OrganizerCore.downloadManager(), SLOT(visitOnNexus(int))); - connect(ui->downloadView, SIGNAL(openFile(int)), m_OrganizerCore.downloadManager(), SLOT(openFile(int))); - connect(ui->downloadView, SIGNAL(openMetaFile(int)), m_OrganizerCore.downloadManager(), SLOT(openMetaFile(int))); - connect(ui->downloadView, SIGNAL(openInDownloadsFolder(int)), m_OrganizerCore.downloadManager(), SLOT(openInDownloadsFolder(int))); - connect(ui->downloadView, SIGNAL(removeDownload(int, bool)), m_OrganizerCore.downloadManager(), SLOT(removeDownload(int, bool))); - connect(ui->downloadView, SIGNAL(restoreDownload(int)), m_OrganizerCore.downloadManager(), SLOT(restoreDownload(int))); - connect(ui->downloadView, SIGNAL(cancelDownload(int)), m_OrganizerCore.downloadManager(), SLOT(cancelDownload(int))); - connect(ui->downloadView, SIGNAL(pauseDownload(int)), m_OrganizerCore.downloadManager(), SLOT(pauseDownload(int))); - connect(ui->downloadView, SIGNAL(resumeDownload(int)), this, SLOT(resumeDownload(int))); -} - -void MainWindow::updateDownloadView() -{ - // this means downlaodTab initialization hasnt happened yet - if (ui->downloadView->model() == nullptr) { - return; - } - // set the view attribute and default row sizes - if (m_OrganizerCore.settings().interface().compactDownloads()) { - ui->downloadView->setProperty("downloadView", "compact"); - setStyleSheet("DownloadListWidget::item { padding: 4px 2px; }"); - } else { - ui->downloadView->setProperty("downloadView", "standard"); - setStyleSheet("DownloadListWidget::item { padding: 16px 4px; }"); - } - //setStyleSheet("DownloadListWidget::item:hover { padding: 0px; }"); - //setStyleSheet("DownloadListWidget::item:selected { padding: 0px; }"); - - // reapply global stylesheet on the widget level (!) to override the defaults - //ui->downloadView->setStyleSheet(styleSheet()); - - ui->downloadView->setMetaDisplay(m_OrganizerCore.settings().interface().metaDownloads()); - ui->downloadView->style()->unpolish(ui->downloadView); - ui->downloadView->style()->polish(ui->downloadView); - qobject_cast(ui->downloadView->header())->customResizeSections(); - m_OrganizerCore.downloadManager()->refreshList(); -} - void MainWindow::modUpdateCheck(std::multimap IDs) { if (m_OrganizerCore.settings().network().offlineMode()) { diff --git a/src/mainwindow.h b/src/mainwindow.h index 7a1c683d..e4c7b851 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -39,6 +39,7 @@ class CategoryFactory; class OrganizerCore; class FilterList; class DataTab; +class DownloadsTab; class BrowserDialog; class PluginListSortProxy; @@ -234,9 +235,6 @@ private: bool populateMenuCategories(QMenu *menu, int targetID); - void initDownloadView(); - void updateDownloadView(); - // remove invalid category-references from mods void fixCategories(); @@ -298,6 +296,7 @@ private: std::unique_ptr m_Filters; std::unique_ptr m_DataTab; + std::unique_ptr m_DownloadsTab; int m_OldProfileIndex; @@ -498,7 +497,6 @@ private slots: void hookUpWindowTutorials(); bool shouldStartTutorial() const; - void resumeDownload(int downloadIndex); void endorseMod(ModInfo::Ptr mod); void unendorseMod(ModInfo::Ptr mod); void trackMod(ModInfo::Ptr mod, bool doTrack); @@ -545,7 +543,6 @@ private slots: void modFilterActive(bool active); void espFilterChanged(const QString &filter); - void downloadFilterChanged(const QString &filter); void expandModList(const QModelIndex &index); @@ -602,7 +599,6 @@ private slots: // ui slots void on_centralWidget_customContextMenuRequested(const QPoint &pos); void on_bsaList_customContextMenuRequested(const QPoint &pos); void on_clearFiltersButton_clicked(); - void on_btnRefreshDownloads_clicked(); void on_executablesListBox_currentIndexChanged(int index); void on_modList_customContextMenuRequested(const QPoint &pos); void on_modList_doubleClicked(const QModelIndex &index); -- cgit v1.3.1 From 106ed49baecc60dbdf4844ed684df750e5caf3aa Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:58:06 -0500 Subject: removed setUpdateDelay(false) calls, it's the default FilterWidget for downloads tab --- src/CMakeLists.txt | 1 - src/createinstancedialogpages.cpp | 1 - src/downloadlist.cpp | 80 ++++++++++++++++++++++++- src/downloadlist.h | 2 + src/downloadlistsortproxy.cpp | 122 -------------------------------------- src/downloadlistsortproxy.h | 58 ------------------ src/downloadlistwidget.cpp | 18 +++++- src/downloadlistwidget.h | 9 +-- src/downloadstab.cpp | 31 ++++------ src/downloadstab.h | 4 +- src/instancemanagerdialog.cpp | 1 - src/mainwindow.cpp | 1 - src/mainwindow.ui | 2 +- src/modinfodialogconflicts.cpp | 6 +- src/modinfodialogimages.cpp | 1 - src/modinfodialogtextfiles.cpp | 1 - 16 files changed, 116 insertions(+), 222 deletions(-) delete mode 100644 src/downloadlistsortproxy.cpp delete mode 100644 src/downloadlistsortproxy.h (limited to 'src/mainwindow.cpp') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fdbe8e38..ce58f7c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,7 +63,6 @@ add_filter(NAME src/dialogs GROUPS add_filter(NAME src/downloads GROUPS downloadlist - downloadlistsortproxy downloadlistwidget downloadmanager ) diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp index a40338dd..c337ba86 100644 --- a/src/createinstancedialogpages.cpp +++ b/src/createinstancedialogpages.cpp @@ -247,7 +247,6 @@ GamePage::GamePage(CreateInstanceDialog& dlg) fillList(); m_filter.setEdit(ui->gamesFilter); - m_filter.setUpdateDelay(0); QObject::connect(&m_filter, &FilterWidget::changed, [&]{ fillList(); }); QObject::connect(ui->showAllGames, &QCheckBox::clicked, [&]{ fillList(); }); diff --git a/src/downloadlist.cpp b/src/downloadlist.cpp index 99347a79..3cfc1fea 100644 --- a/src/downloadlist.cpp +++ b/src/downloadlist.cpp @@ -41,9 +41,14 @@ void DownloadList::setMetaDisplay(bool metaDisplay) } -int DownloadList::rowCount(const QModelIndex&) const +int DownloadList::rowCount(const QModelIndex& parent) const { - return m_Manager->numTotalDownloads() + m_Manager->numPendingDownloads(); + if (!parent.isValid()) { + // root item + return m_Manager->numTotalDownloads() + m_Manager->numPendingDownloads(); + } else { + return 0; + } } @@ -203,3 +208,74 @@ void DownloadList::update(int row) else log::error("invalid row {} in download list, update failed", row); } + +bool DownloadList::lessThan(const QModelIndex &left, const QModelIndex &right) +{ + int leftIndex = left.row(); + int rightIndex = right.row(); + if ((leftIndex < m_Manager->numTotalDownloads()) + && (rightIndex < m_Manager->numTotalDownloads())) { + if (left.column() == DownloadList::COL_NAME) { + return m_Manager->getFileName(left.row()).compare(m_Manager->getFileName(right.row()), Qt::CaseInsensitive) < 0; + } else if (left.column() == DownloadList::COL_MODNAME) { + QString leftName, rightName; + + if (!m_Manager->isInfoIncomplete(left.row())) { + const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(left.row()); + leftName = info->modName; + } + + if (!m_Manager->isInfoIncomplete(right.row())) { + const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(right.row()); + rightName = info->modName; + } + + return leftName.compare(rightName, Qt::CaseInsensitive) < 0; + } else if (left.column() == DownloadList::COL_VERSION) { + MOBase::VersionInfo versionLeft, versionRight; + + if (!m_Manager->isInfoIncomplete(left.row())) { + const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(left.row()); + versionLeft = info->version; + } + + if (!m_Manager->isInfoIncomplete(right.row())) { + const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(right.row()); + versionRight = info->version; + } + + return versionLeft < versionRight; + } else if (left.column() == DownloadList::COL_ID) { + int leftID=0, rightID=0; + + if (!m_Manager->isInfoIncomplete(left.row())) { + const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(left.row()); + leftID = info->modID; + } + + if (!m_Manager->isInfoIncomplete(right.row())) { + const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(right.row()); + rightID = info->modID; + } + + return leftID < rightID; + } else if (left.column() == DownloadList::COL_STATUS) { + DownloadManager::DownloadState leftState = m_Manager->getState(left.row()); + DownloadManager::DownloadState rightState = m_Manager->getState(right.row()); + if (leftState == rightState) + return m_Manager->getFileTime(left.row()) < m_Manager->getFileTime(right.row()); + else + return leftState > rightState; + } else if (left.column() == DownloadList::COL_SIZE) { + return m_Manager->getFileSize(left.row()) < m_Manager->getFileSize(right.row()); + } else if (left.column() == DownloadList::COL_FILETIME) { + return m_Manager->getFileTime(left.row()) < m_Manager->getFileTime(right.row()); + } else if (left.column() == DownloadList::COL_SOURCEGAME) { + return m_Manager->getDisplayGameName(left.row()) < m_Manager->getDisplayGameName(right.row()); + } else { + return leftIndex < rightIndex; + } + } else { + return leftIndex < rightIndex; + } +} diff --git a/src/downloadlist.h b/src/downloadlist.h index eb2bbc55..c40bbac5 100644 --- a/src/downloadlist.h +++ b/src/downloadlist.h @@ -85,6 +85,8 @@ public: **/ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool lessThan(const QModelIndex &left, const QModelIndex &right); + public slots: /** diff --git a/src/downloadlistsortproxy.cpp b/src/downloadlistsortproxy.cpp deleted file mode 100644 index 6209a721..00000000 --- a/src/downloadlistsortproxy.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see . -*/ - -#include "downloadlistsortproxy.h" -#include "downloadlist.h" -#include "downloadmanager.h" -#include "settings.h" - -DownloadListSortProxy::DownloadListSortProxy(const DownloadManager *manager, QObject *parent) - : QSortFilterProxyModel(parent), m_Manager(manager), m_CurrentFilter() -{ -} - -void DownloadListSortProxy::updateFilter(const QString &filter) -{ - m_CurrentFilter = filter; - invalidateFilter(); -} - - -bool DownloadListSortProxy::lessThan(const QModelIndex &left, - const QModelIndex &right) const -{ - int leftIndex = left.row(); - int rightIndex = right.row(); - if ((leftIndex < m_Manager->numTotalDownloads()) - && (rightIndex < m_Manager->numTotalDownloads())) { - if (left.column() == DownloadList::COL_NAME) { - return m_Manager->getFileName(left.row()).compare(m_Manager->getFileName(right.row()), Qt::CaseInsensitive) < 0; - } else if (left.column() == DownloadList::COL_MODNAME) { - QString leftName, rightName; - - if (!m_Manager->isInfoIncomplete(left.row())) { - const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(left.row()); - leftName = info->modName; - } - - if (!m_Manager->isInfoIncomplete(right.row())) { - const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(right.row()); - rightName = info->modName; - } - - return leftName.compare(rightName, Qt::CaseInsensitive) < 0; - } else if (left.column() == DownloadList::COL_VERSION) { - MOBase::VersionInfo versionLeft, versionRight; - - if (!m_Manager->isInfoIncomplete(left.row())) { - const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(left.row()); - versionLeft = info->version; - } - - if (!m_Manager->isInfoIncomplete(right.row())) { - const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(right.row()); - versionRight = info->version; - } - - return versionLeft < versionRight; - } else if (left.column() == DownloadList::COL_ID) { - int leftID=0, rightID=0; - - if (!m_Manager->isInfoIncomplete(left.row())) { - const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(left.row()); - leftID = info->modID; - } - - if (!m_Manager->isInfoIncomplete(right.row())) { - const MOBase::ModRepositoryFileInfo *info = m_Manager->getFileInfo(right.row()); - rightID = info->modID; - } - - return leftID < rightID; - } else if (left.column() == DownloadList::COL_STATUS) { - DownloadManager::DownloadState leftState = m_Manager->getState(left.row()); - DownloadManager::DownloadState rightState = m_Manager->getState(right.row()); - if (leftState == rightState) - return m_Manager->getFileTime(left.row()) < m_Manager->getFileTime(right.row()); - else - return leftState > rightState; - } else if (left.column() == DownloadList::COL_SIZE) { - return m_Manager->getFileSize(left.row()) < m_Manager->getFileSize(right.row()); - } else if (left.column() == DownloadList::COL_FILETIME) { - return m_Manager->getFileTime(left.row()) < m_Manager->getFileTime(right.row()); - } else if (left.column() == DownloadList::COL_SOURCEGAME) { - return m_Manager->getDisplayGameName(left.row()) < m_Manager->getDisplayGameName(right.row()); - } else { - return leftIndex < rightIndex; - } - } else { - return leftIndex < rightIndex; - } -} - - -bool DownloadListSortProxy::filterAcceptsRow(int sourceRow, const QModelIndex&) const -{ - if (m_CurrentFilter.length() == 0) { - return true; - } else if (sourceRow < m_Manager->numTotalDownloads()) { - QString displayedName = Settings::instance().interface().metaDownloads() - ? m_Manager->getDisplayName(sourceRow) - : m_Manager->getFileName(sourceRow); - return displayedName.contains(m_CurrentFilter, Qt::CaseInsensitive); - } else { - return false; - } -} diff --git a/src/downloadlistsortproxy.h b/src/downloadlistsortproxy.h deleted file mode 100644 index 59f46179..00000000 --- a/src/downloadlistsortproxy.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see . -*/ - -#ifndef DOWNLOADLISTSORTPROXY_H -#define DOWNLOADLISTSORTPROXY_H - - -#include - - -class DownloadManager; - - -class DownloadListSortProxy : public QSortFilterProxyModel -{ - Q_OBJECT -public: - - explicit DownloadListSortProxy(const DownloadManager *manager, QObject *parent = 0); - -public slots: - - void updateFilter(const QString &filter); - -protected: - - bool lessThan(const QModelIndex &left, const QModelIndex &right) const; - bool filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const; - -signals: - -public slots: - -private: - - const DownloadManager *m_Manager; - QString m_CurrentFilter; - - -}; - -#endif // DOWNLOADLISTSORTPROXY_H diff --git a/src/downloadlistwidget.cpp b/src/downloadlistwidget.cpp index 1bb13779..ad9ea63a 100644 --- a/src/downloadlistwidget.cpp +++ b/src/downloadlistwidget.cpp @@ -32,9 +32,23 @@ along with Mod Organizer. If not, see . using namespace MOBase; -void DownloadProgressDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +DownloadProgressDelegate::DownloadProgressDelegate( + DownloadManager* manager, DownloadListWidget* list) + : QStyledItemDelegate(list), m_Manager(manager), m_List(list) { - QModelIndex sourceIndex = m_SortProxy->mapToSource(index); +} + +void DownloadProgressDelegate::paint( + QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QModelIndex sourceIndex; + + if (auto* proxy=dynamic_cast(m_List->model())) { + sourceIndex = proxy->mapToSource(index); + } else { + sourceIndex = index; + } + bool pendingDownload = (sourceIndex.row() >= m_Manager->numTotalDownloads()); if (sourceIndex.column() == DownloadList::COL_STATUS && !pendingDownload && m_Manager->getState(sourceIndex.row()) == DownloadManager::STATE_DOWNLOADING) { diff --git a/src/downloadlistwidget.h b/src/downloadlistwidget.h index 784bd275..64e1a6e8 100644 --- a/src/downloadlistwidget.h +++ b/src/downloadlistwidget.h @@ -22,7 +22,6 @@ along with Mod Organizer. If not, see . #include "downloadmanager.h" #include "downloadlist.h" -#include "downloadlistsortproxy.h" #include #include #include @@ -36,19 +35,21 @@ namespace Ui { class DownloadListWidget; } +class DownloadListWidget; + class DownloadProgressDelegate : public QStyledItemDelegate { Q_OBJECT public: - DownloadProgressDelegate(DownloadManager *manager, DownloadListSortProxy *sortProxy, QWidget *parent = 0) : QStyledItemDelegate(parent), m_Manager(manager), m_SortProxy(sortProxy) {} + DownloadProgressDelegate(DownloadManager* manager, DownloadListWidget* list); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; private: - DownloadManager *m_Manager; - DownloadListSortProxy *m_SortProxy; + DownloadManager* m_Manager; + DownloadListWidget* m_List; }; class DownloadListHeader : public QHeaderView diff --git a/src/downloadstab.cpp b/src/downloadstab.cpp index a1a5a474..f5258724 100644 --- a/src/downloadstab.cpp +++ b/src/downloadstab.cpp @@ -1,6 +1,5 @@ #include "downloadstab.h" #include "downloadlist.h" -#include "downloadlistsortproxy.h" #include "downloadlistwidget.h" #include "organizercore.h" #include "ui_mainwindow.h" @@ -13,20 +12,19 @@ DownloadsTab::DownloadsTab(OrganizerCore& core, Ui::MainWindow* mwui) DownloadList *sourceModel = new DownloadList( m_core.downloadManager(), ui.list); - DownloadListSortProxy *sortProxy = new DownloadListSortProxy( - m_core.downloadManager(), ui.list); - - sortProxy->setSourceModel(sourceModel); - connect(ui.filter, SIGNAL(textChanged(QString)), sortProxy, SLOT(updateFilter(QString))); - connect(ui.filter, SIGNAL(textChanged(QString)), this, SLOT(downloadFilterChanged(QString))); - - ui.list->setSourceModel(sourceModel); - ui.list->setModel(sortProxy); + ui.list->setModel(sourceModel); ui.list->setManager(m_core.downloadManager()); ui.list->setItemDelegate(new DownloadProgressDelegate( - m_core.downloadManager(), sortProxy, ui.list)); + m_core.downloadManager(), ui.list)); + update(); + m_filter.setEdit(ui.filter); + m_filter.setList(ui.list); + m_filter.setSortPredicate([sourceModel](auto&& left, auto&& right) { + return sourceModel->lessThan(left, right); + }); + connect(ui.refresh, &QPushButton::clicked, [&]{ refresh(); }); connect(ui.list, SIGNAL(installDownload(int)), &m_core, SLOT(installDownload(int))); connect(ui.list, SIGNAL(queryInfo(int)), m_core.downloadManager(), SLOT(queryInfo(int))); @@ -39,7 +37,7 @@ DownloadsTab::DownloadsTab(OrganizerCore& core, Ui::MainWindow* mwui) connect(ui.list, SIGNAL(restoreDownload(int)), m_core.downloadManager(), SLOT(restoreDownload(int))); connect(ui.list, SIGNAL(cancelDownload(int)), m_core.downloadManager(), SLOT(cancelDownload(int))); connect(ui.list, SIGNAL(pauseDownload(int)), m_core.downloadManager(), SLOT(pauseDownload(int))); - connect(ui.list, SIGNAL(resumeDownload(int)), this, SLOT(resumeDownload(int))); + connect(ui.list, &DownloadListWidget::resumeDownload, [&](int i){ resumeDownload(i); }); } void DownloadsTab::update() @@ -77,12 +75,3 @@ void DownloadsTab::resumeDownload(int downloadIndex) m_core.downloadManager()->resumeDownload(downloadIndex); }); } - -void DownloadsTab::downloadFilterChanged(const QString &filter) -{ - if (!filter.isEmpty()) { - ui.list->setStyleSheet("QTreeView { border: 2px ridge #f00; }"); - } else { - ui.list->setStyleSheet(""); - } -} diff --git a/src/downloadstab.h b/src/downloadstab.h index 3ccdf5f4..ac0cf0e2 100644 --- a/src/downloadstab.h +++ b/src/downloadstab.h @@ -1,6 +1,8 @@ #ifndef MODORGANIZER_DOWNLOADTAB_INCLUDED #define MODORGANIZER_DOWNLOADTAB_INCLUDED +#include + namespace Ui { class MainWindow; } class OrganizerCore; class DownloadListWidget; @@ -25,9 +27,9 @@ private: OrganizerCore& m_core; DownloadsTabUi ui; + MOBase::FilterWidget m_filter; void refresh(); - void downloadFilterChanged(const QString &filter); void resumeDownload(int downloadIndex); }; diff --git a/src/instancemanagerdialog.cpp b/src/instancemanagerdialog.cpp index 00dc57f7..ecc08c1f 100644 --- a/src/instancemanagerdialog.cpp +++ b/src/instancemanagerdialog.cpp @@ -158,7 +158,6 @@ InstanceManagerDialog::InstanceManagerDialog( m_filter.setEdit(ui->filter); m_filter.setList(ui->list); - m_filter.setUpdateDelay(false); m_filter.setFilteredBorder(false); updateInstances(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8777c4ac..5ddc489c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -54,7 +54,6 @@ along with Mod Organizer. If not, see . #include "downloadlistwidget.h" #include "messagedialog.h" #include "installationmanager.h" -#include "downloadlistsortproxy.h" #include "motddialog.h" #include "filedialogmemory.h" #include "tutorialmanager.h" diff --git a/src/mainwindow.ui b/src/mainwindow.ui index dbc6013d..692246fd 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1361,7 +1361,7 @@ p, li { white-space: pre-wrap; } - + Filter the list of downloads. diff --git a/src/modinfodialogconflicts.cpp b/src/modinfodialogconflicts.cpp index cf7f6340..1bfb3218 100644 --- a/src/modinfodialogconflicts.cpp +++ b/src/modinfodialogconflicts.cpp @@ -560,17 +560,14 @@ GeneralConflictsTab::GeneralConflictsTab( m_filterOverwrite.setEdit(ui->overwriteLineEdit); m_filterOverwrite.setList(ui->overwriteTree); m_filterOverwrite.setUseSourceSort(true); - m_filterOverwrite.setUpdateDelay(false); m_filterOverwritten.setEdit(ui->overwrittenLineEdit); m_filterOverwritten.setList(ui->overwrittenTree); m_filterOverwritten.setUseSourceSort(true); - m_filterOverwritten.setUpdateDelay(false); m_filterNoConflicts.setEdit(ui->noConflictLineEdit); m_filterNoConflicts.setList(ui->noConflictTree); m_filterNoConflicts.setUseSourceSort(true); - m_filterNoConflicts.setUpdateDelay(false); QObject::connect( ui->overwriteTree, &QTreeView::doubleClicked, @@ -644,7 +641,7 @@ bool GeneralConflictsTab::update() bool archive = false; const int fileOrigin = file->getOrigin(archive); - + ++m_counts.numTotalFiles; const auto& alternatives = file->getAlternatives(); @@ -895,7 +892,6 @@ AdvancedConflictsTab::AdvancedConflictsTab( m_filter.setEdit(ui->conflictsAdvancedFilter); m_filter.setList(ui->conflictsAdvancedList); m_filter.setUseSourceSort(true); - m_filter.setUpdateDelay(false); // left-elide the overwrites column so that the nearest are visible ui->conflictsAdvancedList->setItemDelegateForColumn( diff --git a/src/modinfodialogimages.cpp b/src/modinfodialogimages.cpp index e27e9686..8a22045e 100644 --- a/src/modinfodialogimages.cpp +++ b/src/modinfodialogimages.cpp @@ -63,7 +63,6 @@ ImagesTab::ImagesTab(ModInfoDialogTabContext cx) : ui->imagesShowDDS->setEnabled(m_ddsAvailable); m_filter.setEdit(ui->imagesFilter); - m_filter.setUpdateDelay(false); connect(&m_filter, &FilterWidget::changed, [&]{ onFilterChanged(); }); connect(ui->imagesExplore, &QAbstractButton::clicked, [&]{ onExplore(); }); diff --git a/src/modinfodialogtextfiles.cpp b/src/modinfodialogtextfiles.cpp index 26ca3eb8..564c2cf7 100644 --- a/src/modinfodialogtextfiles.cpp +++ b/src/modinfodialogtextfiles.cpp @@ -118,7 +118,6 @@ GenericFilesTab::GenericFilesTab( m_filter.setEdit(filter); m_filter.setList(m_list); - m_filter.setUpdateDelay(false); QObject::connect( m_list->selectionModel(), &QItemSelectionModel::currentRowChanged, -- cgit v1.3.1 From 51db1f99f0c4cddc0af224d46d6e5679d18d2a53 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 28 Dec 2020 01:25:33 -0500 Subject: custom browser command changed some places that used QDesktopServices to use shell::Open() from uibase instead --- src/downloadmanager.cpp | 2 +- src/lootdialog.cpp | 2 +- src/mainwindow.cpp | 12 +++--- src/modinfodialognexus.cpp | 12 +++--- src/nxmaccessmanager.cpp | 2 +- src/settings.cpp | 39 +++++++++++++++++++- src/settings.h | 23 ++++++++++-- src/settingsdialog.ui | 90 ++++++++++++++++++++++++++++++++++++--------- src/settingsdialognexus.cpp | 37 +++++++++++++++++-- src/settingsdialognexus.h | 7 +++- 10 files changed, 182 insertions(+), 44 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index c912464d..676b43de 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -1109,7 +1109,7 @@ void DownloadManager::visitOnNexus(int index) QString gameName = info->m_FileInfo->gameName; if (modID > 0) { - QDesktopServices::openUrl(QUrl(m_NexusInterface->getModURL(modID, gameName))); + shell::Open(QUrl(m_NexusInterface->getModURL(modID, gameName))); } else { emit showMessage(tr("Nexus ID for this Mod is unknown")); diff --git a/src/lootdialog.cpp b/src/lootdialog.cpp index 58699d6e..3673c5c6 100644 --- a/src/lootdialog.cpp +++ b/src/lootdialog.cpp @@ -56,7 +56,7 @@ bool MarkdownPage::acceptNavigationRequest(const QUrl &url, NavigationType, bool static const QStringList allowed = {"qrc", "data"}; if (!allowed.contains(url.scheme())) { - QDesktopServices::openUrl(url); + shell::Open(url); return false; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5ddc489c..1e7741ac 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1678,7 +1678,7 @@ void MainWindow::registerModPage(IPluginModPage *modPage) m_IntegratedBrowser->openUrl(modPage->pageURL()); } else { - QDesktopServices::openUrl(QUrl(modPage->pageURL())); + shell::Open(QUrl(modPage->pageURL())); } }, Qt::QueuedConnection); @@ -2408,17 +2408,17 @@ void MainWindow::helpTriggered() void MainWindow::wikiTriggered() { - QDesktopServices::openUrl(QUrl("https://modorganizer2.github.io/")); + shell::Open(QUrl("https://modorganizer2.github.io/")); } void MainWindow::discordTriggered() { - QDesktopServices::openUrl(QUrl("https://discord.gg/cYwdcxj")); + shell::Open(QUrl("https://discord.gg/cYwdcxj")); } void MainWindow::issueTriggered() { - QDesktopServices::openUrl(QUrl("https://github.com/Modorganizer2/modorganizer/issues")); + shell::Open(QUrl("https://github.com/Modorganizer2/modorganizer/issues")); } void MainWindow::tutorialTriggered() @@ -5177,13 +5177,13 @@ void MainWindow::on_actionNexus_triggered() QString gameName = game->gameShortName(); if (game->gameNexusName().isEmpty() && game->primarySources().count()) gameName = game->primarySources()[0]; - QDesktopServices::openUrl(QUrl(NexusInterface::instance().getGameURL(gameName))); + shell::Open(QUrl(NexusInterface::instance().getGameURL(gameName))); } void MainWindow::linkClicked(const QString &url) { - QDesktopServices::openUrl(QUrl(url)); + shell::Open(QUrl(url)); } diff --git a/src/modinfodialognexus.cpp b/src/modinfodialognexus.cpp index 1ee3cefc..f81cfa89 100644 --- a/src/modinfodialognexus.cpp +++ b/src/modinfodialognexus.cpp @@ -217,11 +217,11 @@ void NexusTab::onModChanged() padding-top: 20px; padding-bottom: 20px; } - + img { max-width: 100%; } - + figure.quote { position: relative; padding: 24px; @@ -257,7 +257,7 @@ void NexusTab::onModChanged() display: inline-block; cursor: pointer; } - + details summary::-webkit-details-marker { display:none; } @@ -268,7 +268,7 @@ void NexusTab::onModChanged() a { - /*should avoid overflow with long links forcing wordwrap regardless of spaces*/ + /*should avoid overflow with long links forcing wordwrap regardless of spaces*/ overflow-wrap: break-word; word-wrap: break-word; @@ -325,7 +325,7 @@ void NexusTab::onSourceGameChanged() for (auto game : plugin().plugins()) { if (game->gameName() == ui->sourceGame->currentText()) { - mod().setGameName(game->gameShortName()); + mod().setGameName(game->gameShortName()); mod().setLastNexusQuery(QDateTime::fromSecsSinceEpoch(0)); refreshData(mod().nexusId()); return; @@ -411,7 +411,7 @@ void NexusTab::onCustomURLChanged() void NexusTab::onVisitCustomURL() { - const auto url = mod().parseCustomURL(); + const QUrl url = mod().parseCustomURL(); if (url.isValid()) { shell::Open(url); } diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp index 79c067a2..30108c21 100644 --- a/src/nxmaccessmanager.cpp +++ b/src/nxmaccessmanager.cpp @@ -303,7 +303,7 @@ void NexusSSOLogin::onMessage(const QString& s) // first answer // open browser - const auto url = NexusSSOPage.arg(m_guid); + const QUrl url = NexusSSOPage.arg(m_guid); shell::Open(url); m_timeout.stop(); diff --git a/src/settings.cpp b/src/settings.cpp index ebb4fabe..6445bfbe 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -66,7 +66,8 @@ Settings::Settings(const QString& path, bool globalInstance) : m_Settings(path, QSettings::IniFormat), m_Game(m_Settings), m_Geometry(m_Settings), m_Widgets(m_Settings, globalInstance), m_Colors(m_Settings), - m_Plugins(m_Settings), m_Paths(m_Settings), m_Network(m_Settings), + m_Plugins(m_Settings), m_Paths(m_Settings), + m_Network(m_Settings, globalInstance), m_Nexus(*this, m_Settings), m_Steam(*this, m_Settings), m_Interface(m_Settings), m_Diagnostics(m_Settings) { @@ -1670,9 +1671,21 @@ void PathSettings::setOverwrite(const QString& path) } -NetworkSettings::NetworkSettings(QSettings& settings) +NetworkSettings::NetworkSettings(QSettings& settings, bool globalInstance) : m_Settings(settings) { + if (globalInstance) { + updateCustomBrowser(); + } +} + +void NetworkSettings::updateCustomBrowser() +{ + if (useCustomBrowser()) { + MOBase::shell::SetUrlHandler(customBrowserCommand()); + } else { + MOBase::shell::SetUrlHandler(""); + } } bool NetworkSettings::offlineMode() const @@ -1804,6 +1817,28 @@ void NetworkSettings::updateFromOldMap() updateServers(servers); } +bool NetworkSettings::useCustomBrowser() const +{ + return get(m_Settings, "Settings", "use_custom_browser", false); +} + +void NetworkSettings::setUseCustomBrowser(bool b) +{ + set(m_Settings, "Settings", "use_custom_browser", b); + updateCustomBrowser(); +} + +QString NetworkSettings::customBrowserCommand() const +{ + return get(m_Settings, "Settings", "custom_browser", ""); +} + +void NetworkSettings::setCustomBrowserCommand(const QString& s) +{ + set(m_Settings, "Settings", "custom_browser", s); + updateCustomBrowser(); +} + ServerList NetworkSettings::serversFromOldMap() const { // for 2.2.1 and before diff --git a/src/settings.h b/src/settings.h index 82c3a615..4d1258bf 100644 --- a/src/settings.h +++ b/src/settings.h @@ -447,7 +447,10 @@ private: class NetworkSettings { public: - NetworkSettings(QSettings& settings); + // globalInstance is forwarded from the Settings constructor; NetworkSettings + // will set the global URL custom command + // + NetworkSettings(QSettings& settings, bool globalInstance); // whether the user has disabled online features // @@ -477,6 +480,16 @@ public: // void updateFromOldMap(); + // whether to use a custom command to open links + // + bool useCustomBrowser() const; + void setUseCustomBrowser(bool b); + + // custom command to open links + // + QString customBrowserCommand() const; + void setCustomBrowserCommand(const QString& s); + void dump() const; private: @@ -485,6 +498,10 @@ private: // for pre 2.2.1 ini files // ServerList serversFromOldMap() const; + + // sets the custom command in uibase, called when the settings change + // + void updateCustomBrowser(); }; @@ -693,8 +710,8 @@ public: // any Settings object created with globalInstance==false won't set the // singleton // - // only WidgetSettings need to know whether it created from a globalInstance, - // see its constructor + // some sub-objects like WidgetSettings and NetworkSettings need to know + // whether they were created from a globalInstance, see their constructor // // @param path path to an ini file // @param globalInsance whether this is the global instance; creates the diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index 8670752b..43af5e9f 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -836,7 +836,7 @@ - + @@ -850,16 +850,13 @@ - - - - Disable automatic internet features - - - Disable automatic internet features. This does not affect features that are explicitly invoked by the user (like checking mods for updates, endorsing, opening the web browser) - + + - Offline Mode + Tracked Integration + + + true @@ -873,6 +870,19 @@ + + + + Disable automatic internet features + + + Disable automatic internet features. This does not affect features that are explicitly invoked by the user (like checking mods for updates, endorsing, opening the web browser) + + + Offline Mode + + + @@ -886,14 +896,58 @@ - - - - Tracked Integration - - - true - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Use "%1" as a placeholder for the URL. + + + Use "%1" as a placeholder for the URL. + + + Use "%1" as a placeholder for the URL. + + + Custom browser + + + + + + + Use "%1" as a placeholder for the URL. + + + Use "%1" as a placeholder for the URL. + + + Use "%1" as a placeholder for the URL. + + + + + + + ... + + + + diff --git a/src/settingsdialognexus.cpp b/src/settingsdialognexus.cpp index 461ff8d6..48827a0e 100644 --- a/src/settingsdialognexus.cpp +++ b/src/settingsdialognexus.cpp @@ -300,6 +300,8 @@ NexusSettingsTab::NexusSettingsTab(Settings& s, SettingsDialog& d) ui->endorsementBox->setChecked(settings().nexus().endorsementIntegration()); ui->trackedBox->setChecked(settings().nexus().trackedIntegration()); ui->hideAPICounterBox->setChecked(settings().interface().hideAPICounter()); + ui->useCustomBrowser->setChecked(settings().network().useCustomBrowser()); + ui->browserCommand->setText(settings().network().customBrowserCommand()); // display server preferences for (const auto& server : s.network().servers()) { @@ -345,10 +347,13 @@ NexusSettingsTab::NexusSettingsTab(Settings& s, SettingsDialog& d) [&]{ dialog().setExitNeeded(Exit::Restart); }); - QObject::connect(ui->clearCacheButton, &QPushButton::clicked, [&]{ on_clearCacheButton_clicked(); }); - QObject::connect(ui->associateButton, &QPushButton::clicked, [&]{ on_associateButton_clicked(); }); + QObject::connect(ui->clearCacheButton, &QPushButton::clicked, [&]{ clearCache(); }); + QObject::connect(ui->associateButton, &QPushButton::clicked, [&]{ associate(); }); + QObject::connect(ui->useCustomBrowser, &QCheckBox::clicked, [&]{ updateCustomBrowser(); }); + QObject::connect(ui->browseCustomBrowser, &QPushButton::clicked, [&]{ browseCustomBrowser(); }); updateNexusData(); + updateCustomBrowser(); } void NexusSettingsTab::update() @@ -358,6 +363,8 @@ void NexusSettingsTab::update() settings().nexus().setEndorsementIntegration(ui->endorsementBox->isChecked()); settings().nexus().setTrackedIntegration(ui->trackedBox->isChecked()); settings().interface().setHideAPICounter(ui->hideAPICounterBox->isChecked()); + settings().network().setUseCustomBrowser(ui->useCustomBrowser->isChecked()); + settings().network().setCustomBrowserCommand(ui->browserCommand->text()); auto servers = settings().network().servers(); @@ -407,13 +414,13 @@ void NexusSettingsTab::update() settings().network().updateServers(servers); } -void NexusSettingsTab::on_clearCacheButton_clicked() +void NexusSettingsTab::clearCache() { QDir(Settings::instance().paths().cache()).removeRecursively(); NexusInterface::instance().clearCache(); } -void NexusSettingsTab::on_associateButton_clicked() +void NexusSettingsTab::associate() { Settings::instance().nexus().registerAsNXMHandler(true); } @@ -442,3 +449,25 @@ void NexusSettingsTab::updateNexusData() ui->nexusHourlyRequests->setText(QObject::tr("N/A")); } } + +void NexusSettingsTab::updateCustomBrowser() +{ + ui->browserCommand->setEnabled(ui->useCustomBrowser->isChecked()); +} + +void NexusSettingsTab::browseCustomBrowser () +{ + const QString Filters = + QObject::tr("Executables (*.exe)") + ";;" + + QObject::tr("All Files (*.*)"); + + QString file = QFileDialog::getOpenFileName( + parentWidget(), QObject::tr("Select the browser executable"), + ui->browserCommand->text(), Filters); + + if (file.isNull() || file == "") { + return; + } + + ui->browserCommand->setText(file + " \"%1\""); +} diff --git a/src/settingsdialognexus.h b/src/settingsdialognexus.h index c915accf..a9bd46c7 100644 --- a/src/settingsdialognexus.h +++ b/src/settingsdialognexus.h @@ -65,9 +65,12 @@ public: private: std::unique_ptr m_connectionUI; - void on_clearCacheButton_clicked(); - void on_associateButton_clicked(); + void clearCache(); + void associate(); + void updateNexusData(); + void updateCustomBrowser(); + void browseCustomBrowser(); }; #endif // SETTINGSDIALOGNEXUS_H -- cgit v1.3.1 From 1be20063595206d42ec95a5028b8ecf8f7567476 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 28 Dec 2020 03:12:15 -0500 Subject: offline mode: - don't try to login on startup - don't try to update loot when sorting and display a warning that the master list might be stale --- src/mainwindow.cpp | 31 +++++++++++++++++++++++++------ src/nxmaccessmanager.cpp | 5 +++++ src/organizercore.cpp | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1e7741ac..ce1dc3d1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -6181,10 +6181,22 @@ void MainWindow::on_showHiddenBox_toggled(bool checked) void MainWindow::on_bossButton_clicked() { - const auto r = QMessageBox::question( - this, tr("Sorting plugins"), - tr("Are you sure you want to sort your plugins list?"), - QMessageBox::Yes | QMessageBox::No); + const bool offline = m_OrganizerCore.settings().network().offlineMode(); + + auto r = QMessageBox::No; + + if (offline) { + r = QMessageBox::question( + this, tr("Sorting plugins"), + tr("Are you sure you want to sort your plugins list?") + "\r\n\r\n" + + tr("Note: You are currently in offline mode and LOOT will not update the master list."), + QMessageBox::Yes | QMessageBox::No); + } else { + r = QMessageBox::question( + this, tr("Sorting plugins"), + tr("Are you sure you want to sort your plugins list?"), + QMessageBox::Yes | QMessageBox::No); + } if (r != QMessageBox::Yes) { return; @@ -6196,8 +6208,15 @@ void MainWindow::on_bossButton_clicked() setEnabled(false); ON_BLOCK_EXIT([&] () { setEnabled(true); }); - if (runLoot(this, m_OrganizerCore, m_DidUpdateMasterList)) { - m_DidUpdateMasterList = true; + // don't try to update the master list in offline mode + const bool didUpdateMasterList = offline ? true : m_DidUpdateMasterList; + + if (runLoot(this, m_OrganizerCore, didUpdateMasterList)) { + // don't assume the master list was updated in offline mode + if (!offline) { + m_DidUpdateMasterList = true; + } + m_OrganizerCore.refreshESPList(false); m_OrganizerCore.savePluginList(); } diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp index 30108c21..001e1bb1 100644 --- a/src/nxmaccessmanager.cpp +++ b/src/nxmaccessmanager.cpp @@ -935,6 +935,11 @@ void NXMAccessManager::apiCheck(const QString &apiKey, bool force) return; } + if (m_Settings && m_Settings->network().offlineMode()) { + m_validationState = NotChecked; + return; + } + if (force) { m_validationState = NotChecked; } diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 631e49be..569faccb 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1430,7 +1430,7 @@ void OrganizerCore::loggedInAction(QWidget* parent, std::function f) { if (NexusInterface::instance().getAccessManager()->validated()) { f(); - } else { + } else if (!m_Settings.network().offlineMode()) { QString apiKey; if (GlobalSettings::nexusApiKey(apiKey)) { doAfterLogin([f]{ f(); }); -- cgit v1.3.1 From 3c62a048da24ae58d5d9d490914ba9e8dbdc89f0 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 28 Dec 2020 03:37:20 -0500 Subject: fixed crash for ignore data/mark converted on multiple mods also fixes only half the selected items being handled at a time the selection must be copied first because it's live and will get invalidated when filters are being used there was some weird connect() calls for every item, not sure why --- src/mainwindow.cpp | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ce1dc3d1..6c3801da 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3118,41 +3118,51 @@ void MainWindow::displayModInformation(int row, ModInfoTabIDs tabID) void MainWindow::ignoreMissingData_clicked() { - QItemSelectionModel *selection = ui->modList->selectionModel(); - if (selection->hasSelection() && selection->selectedRows().count() > 1) { - for (QModelIndex idx : selection->selectedRows()) { + const auto rows = ui->modList->selectionModel()->selectedRows(); + + if (rows.count() > 1) { + std::vector changed; + + for (QModelIndex idx : rows) { int row_idx = idx.data(Qt::UserRole + 1).toInt(); ModInfo::Ptr info = ModInfo::getByIndex(row_idx); info->markValidated(true); - connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex))); + changed.push_back(info); + } - emit modListDataChanged(m_OrganizerCore.modList()->index(row_idx, 0), m_OrganizerCore.modList()->index(row_idx, m_OrganizerCore.modList()->columnCount() - 1)); + for (auto&& m : changed) { + int row_idx = ModInfo::getIndex(m->internalName()); + m_OrganizerCore.modList()->notifyChange(row_idx); } } else { ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); info->markValidated(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)); + m_OrganizerCore.modList()->notifyChange(m_ContextRow); } } void MainWindow::markConverted_clicked() { - QItemSelectionModel *selection = ui->modList->selectionModel(); - if (selection->hasSelection() && selection->selectedRows().count() > 1) { - for (QModelIndex idx : selection->selectedRows()) { + const auto rows = ui->modList->selectionModel()->selectedRows(); + + if (rows.count() > 1) { + std::vector changed; + + for (QModelIndex idx : rows) { 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)); + changed.push_back(info); + } + + for (auto&& m : changed) { + int row_idx = ModInfo::getIndex(m->internalName()); + m_OrganizerCore.modList()->notifyChange(row_idx); } } 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)); + m_OrganizerCore.modList()->notifyChange(m_ContextRow); } } -- cgit v1.3.1 From 462ea08c348b6c524691e435ea7fb911ffd2367e Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 28 Dec 2020 04:17:16 -0500 Subject: fixed warning about ini files with utf8 bom fixed main thread name still getting clobbered by QWebEngine --- src/mainwindow.cpp | 4 ++++ src/moapplication.cpp | 3 --- src/settings.cpp | 29 ++++++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 4 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6c3801da..37e0027d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -286,6 +286,10 @@ MainWindow::MainWindow(Settings &settings QWebEngineProfile::defaultProfile()->setCachePath(settings.paths().cache()); QWebEngineProfile::defaultProfile()->setPersistentStoragePath(settings.paths().cache()); + // qt resets the thread name somewhere within the QWebEngineProfile calls + // above + MOShared::SetThisThreadName("main"); + ui->setupUi(this); languageChange(settings.interface().language()); ui->statusBar->setup(ui, settings); diff --git a/src/moapplication.cpp b/src/moapplication.cpp index 88b5710f..fb6a7121 100644 --- a/src/moapplication.cpp +++ b/src/moapplication.cpp @@ -359,9 +359,6 @@ int MOApplication::doOneRun(MOMultiProcess& multiProcess) tt.start("MOApplication::doOneRun() MainWindow setup"); MainWindow mainWindow(settings, organizer, *pluginContainer); - // qt resets the thread name somewhere when creating the main window - MOShared::SetThisThreadName("main"); - // the nexus interface can show dialogs, make sure they're parented to the // main window ni.getAccessManager()->setTopLevelWidget(&mainWindow); diff --git a/src/settings.cpp b/src/settings.cpp index 6445bfbe..f5ad83a7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -470,7 +470,34 @@ const DiagnosticsSettings& Settings::diagnostics() const QSettings::Status Settings::sync() const { m_Settings.sync(); - return m_Settings.status(); + + const auto s = m_Settings.status(); + + // there's a bug in Qt at least until 5.15.0 where a utf-8 bom in the ini is + // handled correctly but still sets FormatError + // + // see qsettings.cpp, in QConfFileSettingsPrivate::readIniFile(), there's a + // specific check for utf-8, which adjusts `dataPos` so it's skipped, but + // the FLUSH_CURRENT_SECTION() macro uses `currentSectionStart`, and that one + // isn't adjusted when changing `dataPos` on the first line and so stays 0 + // + // this puts the bom in `unparsedIniSections` and eventually sets FormatError + // somewhere + // + // + // the other problem is that the status is never reset, not even when calling + // sync(), so the FormatError that's returned here is actually from reading + // the ini, not writing it + // + // + // since it's impossible to get a FormatError on write, it's considered to + // be a NoError here + + if (s == QSettings::FormatError) { + return QSettings::NoError; + } else { + return s; + } } QSettings::Status Settings::iniStatus() const -- cgit v1.3.1 From a8f6f0d7a0f1c8506e225dc5a817cadc0c0b3662 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 28 Dec 2020 05:28:37 -0500 Subject: split saves tab, no changes --- src/CMakeLists.txt | 1 + src/mainwindow.cpp | 276 ++++------------------------------------------------ src/mainwindow.h | 27 +----- src/savestab.cpp | 278 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/savestab.h | 60 ++++++++++++ 5 files changed, 359 insertions(+), 283 deletions(-) create mode 100644 src/savestab.cpp create mode 100644 src/savestab.h (limited to 'src/mainwindow.cpp') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ce58f7c2..98bbe05f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -105,6 +105,7 @@ add_filter(NAME src/mainwindow GROUPS filetreemodel filterlist mainwindow + savestab statusbar ) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 37e0027d..e7d99f23 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -49,7 +49,6 @@ along with Mod Organizer. If not, see . #include "categoriesdialog.h" #include "modinfodialog.h" #include "overwriteinfodialog.h" -#include "activatemodsdialog.h" #include "downloadlist.h" #include "downloadlistwidget.h" #include "messagedialog.h" @@ -76,6 +75,7 @@ along with Mod Organizer. If not, see . #include "filterlist.h" #include "datatab.h" #include "downloadstab.h" +#include "savestab.h" #include "instancemanagerdialog.h" #include #include @@ -260,7 +260,6 @@ MainWindow::MainWindow(Settings &settings , m_ContextItem(nullptr) , m_ContextAction(nullptr) , m_ContextRow(-1) - , m_CurrentSaveView(nullptr) , m_OrganizerCore(organizerCore) , m_PluginContainer(pluginContainer) , m_DidUpdateMasterList(false) @@ -373,6 +372,8 @@ MainWindow::MainWindow(Settings &settings // downloads tab m_DownloadsTab.reset(new DownloadsTab(m_OrganizerCore, ui)); + // saves tab + m_SavesTab.reset(new SavesTab(this, m_OrganizerCore, ui)); // Hide stuff we do not need: IPluginGame const* game = m_OrganizerCore.managedGame(); @@ -403,9 +404,6 @@ MainWindow::MainWindow(Settings &settings ui->openFolderMenu->setMenu(openFolderMenu()); - ui->savegameList->installEventFilter(this); - ui->savegameList->setMouseTracking(true); - // don't allow mouse wheel to switch grouping, too many people accidentally // turn on grouping and then don't understand what happened EventFilter *noWheel @@ -423,8 +421,6 @@ MainWindow::MainWindow(Settings &settings connect(&m_PluginContainer, SIGNAL(diagnosisUpdate()), this, SLOT(scheduleCheckForProblems())); - connect(ui->savegameList, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(saveSelectionChanged(QListWidgetItem*))); - connect(m_ModListSortProxy, SIGNAL(filterActive(bool)), this, SLOT(modFilterActive(bool))); connect(m_ModListSortProxy, SIGNAL(layoutChanged()), this, SLOT(updateModCount())); connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString))); @@ -439,11 +435,6 @@ MainWindow::MainWindow(Settings &settings this, &MainWindow::refresherProgress); connect(m_OrganizerCore.directoryRefresher(), SIGNAL(error(QString)), this, SLOT(showError(QString))); - m_SavesWatcherTimer.setSingleShot(true); - m_SavesWatcherTimer.setInterval(500); - connect(&m_SavesWatcher, &QFileSystemWatcher::directoryChanged, [this]() { m_SavesWatcherTimer.start(); }); - connect(&m_SavesWatcherTimer, &QTimer::timeout, this, &MainWindow::refreshSavesIfOpen); - connect(&m_OrganizerCore.settings(), SIGNAL(languageChanged(QString)), this, SLOT(languageChange(QString))); connect(&m_OrganizerCore.settings(), SIGNAL(styleChanged(QString)), this, SIGNAL(styleChanged(QString))); @@ -496,7 +487,6 @@ MainWindow::MainWindow(Settings &settings 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())); setFilterShortcuts(ui->modList, ui->modFilterEdit); @@ -727,7 +717,6 @@ MainWindow::~MainWindow() } } - void MainWindow::updateWindowTitle(const APIUserAccount& user) { //"\xe2\x80\x93" is an "em dash", a longer "-" @@ -1512,78 +1501,11 @@ void MainWindow::cleanup() m_MetaSave.waitForFinished(); } -void MainWindow::displaySaveGameInfo(QListWidgetItem *newItem) -{ - // don't display the widget if the main window doesn't have focus - // - // this goes against the standard behaviour for tooltips, which are displayed - // on hover regardless of focus, but this widget is so large and busy that - // it's probably better this way - if (!isActiveWindow()){ - return; - } - - if (m_CurrentSaveView == nullptr) { - IPluginGame const *game = m_OrganizerCore.managedGame(); - SaveGameInfo const *info = game->feature(); - if (info != nullptr) { - m_CurrentSaveView = info->getSaveGameWidget(this); - } - if (m_CurrentSaveView == nullptr) { - return; - } - } - m_CurrentSaveView->setSave(*m_SaveGames[ui->savegameList->row(newItem)]); - - QWindow *window = m_CurrentSaveView->window()->windowHandle(); - QRect screenRect; - if (window == nullptr) - screenRect = QGuiApplication::primaryScreen()->geometry(); - else - screenRect = window->screen()->geometry(); - - QPoint pos = QCursor::pos(); - if (pos.x() + m_CurrentSaveView->width() > screenRect.right()) { - pos.rx() -= (m_CurrentSaveView->width() + 2); - } else { - pos.rx() += 5; - } - - if (pos.y() + m_CurrentSaveView->height() > screenRect.bottom()) { - pos.ry() -= (m_CurrentSaveView->height() + 10); - } else { - pos.ry() += 20; - } - m_CurrentSaveView->move(pos); - - m_CurrentSaveView->show(); - m_CurrentSaveView->setProperty("displayItem", QVariant::fromValue(static_cast(newItem))); -} - - -void MainWindow::saveSelectionChanged(QListWidgetItem *newItem) -{ - if (newItem == nullptr) { - hideSaveGameInfo(); - } else if (m_CurrentSaveView == nullptr || newItem != m_CurrentSaveView->property("displayItem").value()) { - displaySaveGameInfo(newItem); - } -} - - -void MainWindow::hideSaveGameInfo() -{ - if (m_CurrentSaveView != nullptr) { - m_CurrentSaveView->deleteLater(); - m_CurrentSaveView = nullptr; - } -} - bool MainWindow::eventFilter(QObject *object, QEvent *event) { if ((object == ui->savegameList) && ((event->type() == QEvent::Leave) || (event->type() == QEvent::WindowDeactivate))) { - hideSaveGameInfo(); + m_SavesTab->hideSaveGameInfo(); } else if (event->type() == QEvent::StatusTip && object != this) { QMainWindow::event(event); return true; @@ -1759,7 +1681,7 @@ void MainWindow::activateSelectedProfile() m_ModListSortProxy->setProfile(m_OrganizerCore.currentProfile()); - refreshSaveList(); + m_SavesTab->refreshSaveList(); m_OrganizerCore.refresh(); updateModCount(); updatePluginCount(); @@ -1805,14 +1727,16 @@ void MainWindow::on_profileBox_currentIndexChanged(int index) LocalSavegames *saveGames = m_OrganizerCore.managedGame()->feature(); if (saveGames != nullptr) { - if (saveGames->prepareProfile(m_OrganizerCore.currentProfile())) - refreshSaveList(); + if (saveGames->prepareProfile(m_OrganizerCore.currentProfile())) { + m_SavesTab->refreshSaveList(); + } } BSAInvalidation *invalidation = m_OrganizerCore.managedGame()->feature(); if (invalidation != nullptr) { - if (invalidation->prepareProfile(m_OrganizerCore.currentProfile())) + if (invalidation->prepareProfile(m_OrganizerCore.currentProfile())) { QTimer::singleShot(5, &m_OrganizerCore, SLOT(profileRefresh())); + } } } } @@ -1898,78 +1822,6 @@ void MainWindow::refreshExecutablesList() ui->executablesListBox->setEnabled(true); } -void MainWindow::refreshSavesIfOpen() -{ - if (ui->tabWidget->currentWidget() == ui->savesTab) { - refreshSaveList(); - } -} - -QDir MainWindow::currentSavesDir() const -{ - QDir savesDir; - if (m_OrganizerCore.currentProfile()->localSavesEnabled()) { - savesDir.setPath(m_OrganizerCore.currentProfile()->savePath()); - } else { - auto iniFiles = m_OrganizerCore.managedGame()->iniFiles(); - - if (iniFiles.isEmpty()) { - return m_OrganizerCore.managedGame()->savesDirectory(); - } - - QString iniPath = m_OrganizerCore.currentProfile()->absoluteIniFilePath(iniFiles[0]); - - wchar_t path[MAX_PATH]; - if (::GetPrivateProfileStringW( - L"General", L"SLocalSavePath", L"", - path, MAX_PATH, - iniPath.toStdWString().c_str() - )) { - savesDir.setPath(m_OrganizerCore.managedGame()->documentsDirectory().absoluteFilePath(QString::fromWCharArray(path))); - } - else { - savesDir = m_OrganizerCore.managedGame()->savesDirectory(); - } - } - - return savesDir; -} - -void MainWindow::startMonitorSaves() -{ - stopMonitorSaves(); - - QDir savesDir = currentSavesDir(); - - m_SavesWatcher.addPath(savesDir.absolutePath()); -} - -void MainWindow::stopMonitorSaves() -{ - if (m_SavesWatcher.directories().length() > 0) { - m_SavesWatcher.removePaths(m_SavesWatcher.directories()); - } -} - -void MainWindow::refreshSaveList() -{ - TimeThis tt("MainWindow::refreshSaveList()"); - - startMonitorSaves(); // re-starts monitoring - - QDir savesDir = currentSavesDir(); - MOBase::log::debug("reading save games from {}", savesDir.absolutePath()); - m_SaveGames = m_OrganizerCore.managedGame()->listSaves(savesDir); - std::sort(m_SaveGames.begin(), m_SaveGames.end(), [](auto const& lhs, auto const& rhs) { - return lhs->getCreationTime() > rhs->getCreationTime(); - }); - - ui->savegameList->clear(); - for (auto& save: m_SaveGames) { - ui->savegameList->addItem(savesDir.relativeFilePath(save->getFilepath())); - } -} - static bool BySortValue(const std::pair &LHS, const std::pair &RHS) { return LHS.first < RHS.first; @@ -2320,7 +2172,7 @@ void MainWindow::on_tabWidget_currentChanged(int index) } else if (currentWidget == ui->dataTab) { m_DataTab->activated(); } else if (currentWidget == ui->savesTab) { - refreshSaveList(); + m_SavesTab->refreshSaveList(); } } @@ -2452,9 +2304,9 @@ void MainWindow::on_actionAdd_Profile_triggered() // workaround: need to disable monitoring of the saves directory, otherwise the active // profile directory is locked - stopMonitorSaves(); + m_SavesTab->stopMonitorSaves(); profilesDialog.exec(); - refreshSaveList(); // since the save list may now be outdated we have to refresh it completely + m_SavesTab->refreshSaveList(); // since the save list may now be outdated we have to refresh it completely if (refreshProfiles() && !profilesDialog.failed()) { break; @@ -2463,14 +2315,16 @@ void MainWindow::on_actionAdd_Profile_triggered() LocalSavegames *saveGames = m_OrganizerCore.managedGame()->feature(); if (saveGames != nullptr) { - if (saveGames->prepareProfile(m_OrganizerCore.currentProfile())) - refreshSaveList(); + if (saveGames->prepareProfile(m_OrganizerCore.currentProfile())) { + m_SavesTab->refreshSaveList(); + } } BSAInvalidation *invalidation = m_OrganizerCore.managedGame()->feature(); if (invalidation != nullptr) { - if (invalidation->prepareProfile(m_OrganizerCore.currentProfile())) + if (invalidation->prepareProfile(m_OrganizerCore.currentProfile())) { QTimer::singleShot(5, &m_OrganizerCore, SLOT(profileRefresh())); + } } } @@ -4923,100 +4777,6 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) } } - -void MainWindow::deleteSavegame_clicked() -{ - SaveGameInfo const *info = m_OrganizerCore.managedGame()->feature(); - - QString savesMsgLabel; - QStringList deleteFiles; - - int count = 0; - - for (const QModelIndex &idx : ui->savegameList->selectionModel()->selectedIndexes()) { - - auto& saveGame = m_SaveGames[idx.row()]; - - if (count < 10) { - savesMsgLabel += "
  • " + QFileInfo(saveGame->getFilepath()).completeBaseName() + "
  • "; - } - ++count; - - deleteFiles += saveGame->allFiles(); - } - - if (count > 10) { - savesMsgLabel += "
  • ... " + tr("%1 more").arg(count - 10) + "
  • "; - } - - if (QMessageBox::question(this, tr("Confirm"), - tr("Are you sure you want to remove the following %n save(s)?
    " - "
      %1

    " - "Removed saves will be sent to the Recycle Bin.", "", count) - .arg(savesMsgLabel), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - shellDelete(deleteFiles, true); // recycle bin delete. - refreshSaveList(); - } -} - - -void MainWindow::fixMods_clicked(SaveGameInfo::MissingAssets const &missingAssets) -{ - ActivateModsDialog dialog(missingAssets, this); - if (dialog.exec() == QDialog::Accepted) { - // activate the required mods, then enable all esps - std::set modsToActivate = dialog.getModsToActivate(); - for (std::set::iterator iter = modsToActivate.begin(); iter != modsToActivate.end(); ++iter) { - if ((*iter != "") && (*iter != "")) { - unsigned int modIndex = ModInfo::getIndex(*iter); - m_OrganizerCore.currentProfile()->setModEnabled(modIndex, true); - } - } - - m_OrganizerCore.currentProfile()->writeModlist(); - m_OrganizerCore.refreshLists(); - - std::set espsToActivate = dialog.getESPsToActivate(); - for (std::set::iterator iter = espsToActivate.begin(); iter != espsToActivate.end(); ++iter) { - m_OrganizerCore.pluginList()->enableESP(*iter); - } - m_OrganizerCore.saveCurrentLists(); - } -} - - -void MainWindow::on_savegameList_customContextMenuRequested(const QPoint& pos) -{ - QItemSelectionModel* selection = ui->savegameList->selectionModel(); - - if (!selection->hasSelection()) { - return; - } - - QMenu menu; - - SaveGameInfo const* info = this->m_OrganizerCore.managedGame()->feature(); - if (info != nullptr) { - QAction* action = menu.addAction(tr("Enable Mods...")); - action->setEnabled(false); - if (selection->selectedIndexes().count() == 1) { - auto& save = m_SaveGames[selection->selectedIndexes()[0].row()]; - SaveGameInfo::MissingAssets missing = info->getMissingAssets(*save); - if (missing.size() != 0) { - connect(action, &QAction::triggered, this, [this, missing] { fixMods_clicked(missing); }); - action->setEnabled(true); - } - } - } - - QString deleteMenuLabel = tr("Delete %n save(s)", "", selection->selectedIndexes().count()); - - menu.addAction(deleteMenuLabel, this, SLOT(deleteSavegame_clicked())); - - menu.exec(ui->savegameList->viewport()->mapToGlobal(pos)); -} - void MainWindow::linkToolbar() { Executable* exe = getSelectedExecutable(); diff --git a/src/mainwindow.h b/src/mainwindow.h index e4c7b851..eae150d6 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -27,7 +27,6 @@ along with Mod Organizer. If not, see . #include "iuserinterface.h" #include "modinfo.h" #include "modlistsortproxy.h" -#include "savegameinfo.h" #include "tutorialcontrol.h" #include "plugincontainer.h" //class PluginContainer; #include "iplugingame.h" //namespace MOBase { class IPluginGame; } @@ -40,6 +39,7 @@ class OrganizerCore; class FilterList; class DataTab; class DownloadsTab; +class SavesTab; class BrowserDialog; class PluginListSortProxy; @@ -47,7 +47,6 @@ namespace BSA { class Archive; } namespace MOBase { class IPluginModPage; } namespace MOBase { class IPluginTool; } -namespace MOBase { class ISaveGame; } namespace MOShared { class DirectoryEntry; } @@ -123,7 +122,6 @@ public: bool addProfile(); void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives); - void refreshSaveList(); void setModListSorting(int index); void setESPListSorting(int index); @@ -245,8 +243,6 @@ private: void setCategoryListVisible(bool visible); - void displaySaveGameInfo(QListWidgetItem *newItem); - bool errorReported(QString &logFile); void updateESPLock(bool locked); @@ -263,11 +259,6 @@ private: QMenu *openFolderMenu(); - QDir currentSavesDir() const; - - void startMonitorSaves(); - void stopMonitorSaves(); - void dropLocalFile(const QUrl &url, const QString &outputDir, bool move); void sendSelectedModsToPriority(int newPriority); @@ -297,6 +288,7 @@ private: std::unique_ptr m_Filters; std::unique_ptr m_DataTab; std::unique_ptr m_DownloadsTab; + std::unique_ptr m_SavesTab; int m_OldProfileIndex; @@ -324,9 +316,6 @@ private: QFuture m_MetaSave; QTime m_StartTime; - //SaveGameInfoWidget *m_CurrentSaveView; - std::vector> m_SaveGames; - MOBase::ISaveGameInfoWidget *m_CurrentSaveView; OrganizerCore &m_OrganizerCore; PluginContainer &m_PluginContainer; @@ -336,9 +325,6 @@ private: std::unique_ptr m_IntegratedBrowser; - QTimer m_SavesWatcherTimer; - QFileSystemWatcher m_SavesWatcher; - QByteArray m_ArchiveListHash; bool m_DidUpdateMasterList; @@ -360,7 +346,6 @@ private: Executable* getSelectedExecutable(); private slots: - void updateWindowTitle(const APIUserAccount& user); void showMessage(const QString &message); void showError(const QString &message); @@ -410,9 +395,6 @@ private slots: void sendSelectedModsToBottom_clicked(); void sendSelectedModsToPriority_clicked(); void sendSelectedModsToSeparator_clicked(); - // savegame context menu - void deleteSavegame_clicked(); - void fixMods_clicked(SaveGameInfo::MissingAssets const &missingAssets); // data-tree context menu // pluginlist context menu @@ -427,7 +409,6 @@ private slots: void linkMenu(); void languageChange(const QString &newLanguage); - void saveSelectionChanged(QListWidgetItem *newItem); void windowTutorialFinished(const QString &windowName); @@ -492,8 +473,6 @@ private slots: void modRenamed(const QString &oldName, const QString &newName); void modRemoved(const QString &fileName); - void hideSaveGameInfo(); - void hookUpWindowTutorials(); bool shouldStartTutorial() const; @@ -562,7 +541,6 @@ private slots: void ignoreUpdate(); void unignoreUpdate(); - void refreshSavesIfOpen(); void about(); void modListSortIndicatorChanged(int column, Qt::SortOrder order); @@ -605,7 +583,6 @@ private slots: // ui slots void on_listOptionsBtn_pressed(); void on_espList_doubleClicked(const QModelIndex &index); void on_profileBox_currentIndexChanged(int index); - void on_savegameList_customContextMenuRequested(const QPoint &pos); void on_startButton_clicked(); void on_tabWidget_currentChanged(int index); diff --git a/src/savestab.cpp b/src/savestab.cpp new file mode 100644 index 00000000..a14321d3 --- /dev/null +++ b/src/savestab.cpp @@ -0,0 +1,278 @@ +#include "savestab.h" +#include "ui_mainwindow.h" +#include "organizercore.h" +#include "activatemodsdialog.h" +#include +#include + +using namespace MOBase; + +SavesTab::SavesTab(QWidget* window, OrganizerCore& core, Ui::MainWindow* mwui) + : m_window(window), m_core(core), m_CurrentSaveView(nullptr), ui{ + mwui->tabWidget, mwui->savesTab, mwui->savegameList} +{ + m_SavesWatcherTimer.setSingleShot(true); + m_SavesWatcherTimer.setInterval(500); + + ui.list->installEventFilter(this); + ui.list->setMouseTracking(true); + + connect( + &m_SavesWatcher, &QFileSystemWatcher::directoryChanged, + [&]{ m_SavesWatcherTimer.start(); }); + + connect( + &m_SavesWatcherTimer, &QTimer::timeout, + [&]{ refreshSavesIfOpen(); }); + + connect( + ui.list, &QWidget::customContextMenuRequested, + [&](auto pos){ onContextMenu(pos); }); + + connect( + ui.list, &QListWidget::itemEntered, + [&](auto* item){ saveSelectionChanged(item); }); +} + +void SavesTab::displaySaveGameInfo(QListWidgetItem *newItem) +{ + // don't display the widget if the main window doesn't have focus + // + // this goes against the standard behaviour for tooltips, which are displayed + // on hover regardless of focus, but this widget is so large and busy that + // it's probably better this way + if (!m_window->isActiveWindow()){ + return; + } + + if (m_CurrentSaveView == nullptr) { + const IPluginGame* game = m_core.managedGame(); + const SaveGameInfo* info = game->feature(); + + if (info != nullptr) { + m_CurrentSaveView = info->getSaveGameWidget(m_window); + } + + if (m_CurrentSaveView == nullptr) { + return; + } + } + + m_CurrentSaveView->setSave(*m_SaveGames[ui.list->row(newItem)]); + + QWindow *window = m_CurrentSaveView->window()->windowHandle(); + QRect screenRect; + if (window == nullptr) + screenRect = QGuiApplication::primaryScreen()->geometry(); + else + screenRect = window->screen()->geometry(); + + QPoint pos = QCursor::pos(); + if (pos.x() + m_CurrentSaveView->width() > screenRect.right()) { + pos.rx() -= (m_CurrentSaveView->width() + 2); + } else { + pos.rx() += 5; + } + + if (pos.y() + m_CurrentSaveView->height() > screenRect.bottom()) { + pos.ry() -= (m_CurrentSaveView->height() + 10); + } else { + pos.ry() += 20; + } + m_CurrentSaveView->move(pos); + + m_CurrentSaveView->show(); + m_CurrentSaveView->setProperty("displayItem", QVariant::fromValue(static_cast(newItem))); +} + + +void SavesTab::saveSelectionChanged(QListWidgetItem *newItem) +{ + if (newItem == nullptr) { + hideSaveGameInfo(); + } else if (m_CurrentSaveView == nullptr || newItem != m_CurrentSaveView->property("displayItem").value()) { + displaySaveGameInfo(newItem); + } +} + + +void SavesTab::hideSaveGameInfo() +{ + if (m_CurrentSaveView != nullptr) { + m_CurrentSaveView->deleteLater(); + m_CurrentSaveView = nullptr; + } +} + +void SavesTab::refreshSavesIfOpen() +{ + if (ui.mainTabs->currentWidget() == ui.tab) { + refreshSaveList(); + } +} + +QDir SavesTab::currentSavesDir() const +{ + QDir savesDir; + if (m_core.currentProfile()->localSavesEnabled()) { + savesDir.setPath(m_core.currentProfile()->savePath()); + } else { + auto iniFiles = m_core.managedGame()->iniFiles(); + + if (iniFiles.isEmpty()) { + return m_core.managedGame()->savesDirectory(); + } + + QString iniPath = m_core.currentProfile()->absoluteIniFilePath(iniFiles[0]); + + wchar_t path[MAX_PATH]; + if (::GetPrivateProfileStringW( + L"General", L"SLocalSavePath", L"", + path, MAX_PATH, + iniPath.toStdWString().c_str() + )) { + savesDir.setPath(m_core.managedGame()->documentsDirectory().absoluteFilePath(QString::fromWCharArray(path))); + } + else { + savesDir = m_core.managedGame()->savesDirectory(); + } + } + + return savesDir; +} + +void SavesTab::startMonitorSaves() +{ + stopMonitorSaves(); + + QDir savesDir = currentSavesDir(); + + m_SavesWatcher.addPath(savesDir.absolutePath()); +} + +void SavesTab::stopMonitorSaves() +{ + if (m_SavesWatcher.directories().length() > 0) { + m_SavesWatcher.removePaths(m_SavesWatcher.directories()); + } +} + +void SavesTab::refreshSaveList() +{ + TimeThis tt("MainWindow::refreshSaveList()"); + + startMonitorSaves(); // re-starts monitoring + + try + { + QDir savesDir = currentSavesDir(); + MOBase::log::debug("reading save games from {}", savesDir.absolutePath()); + m_SaveGames = m_core.managedGame()->listSaves(savesDir); + std::sort(m_SaveGames.begin(), m_SaveGames.end(), [](auto const& lhs, auto const& rhs) { + return lhs->getCreationTime() > rhs->getCreationTime(); + }); + + ui.list->clear(); + for (auto& save: m_SaveGames) { + ui.list->addItem(savesDir.relativeFilePath(save->getFilepath())); + } + } + catch(std::exception& e) + { + // listSaves() can throw + log::error("{}", e.what()); + } +} + +void SavesTab::deleteSavegame() +{ + SaveGameInfo const *info = m_core.managedGame()->feature(); + + QString savesMsgLabel; + QStringList deleteFiles; + + int count = 0; + + for (const QModelIndex &idx : ui.list->selectionModel()->selectedIndexes()) { + + auto& saveGame = m_SaveGames[idx.row()]; + + if (count < 10) { + savesMsgLabel += "
  • " + QFileInfo(saveGame->getFilepath()).completeBaseName() + "
  • "; + } + ++count; + + deleteFiles += saveGame->allFiles(); + } + + if (count > 10) { + savesMsgLabel += "
  • ... " + tr("%1 more").arg(count - 10) + "
  • "; + } + + if (QMessageBox::question(m_window, tr("Confirm"), + tr("Are you sure you want to remove the following %n save(s)?
    " + "
      %1

    " + "Removed saves will be sent to the Recycle Bin.", "", count) + .arg(savesMsgLabel), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + shellDelete(deleteFiles, true); // recycle bin delete. + refreshSaveList(); + } +} + + +void SavesTab::onContextMenu(const QPoint& pos) +{ + QItemSelectionModel* selection = ui.list->selectionModel(); + + if (!selection->hasSelection()) { + return; + } + + QMenu menu; + + SaveGameInfo const* info = this->m_core.managedGame()->feature(); + if (info != nullptr) { + QAction* action = menu.addAction(tr("Fix enabled mods...")); + action->setEnabled(false); + if (selection->selectedIndexes().count() == 1) { + auto& save = m_SaveGames[selection->selectedIndexes()[0].row()]; + SaveGameInfo::MissingAssets missing = info->getMissingAssets(*save); + if (missing.size() != 0) { + connect(action, &QAction::triggered, this, [this, missing] { fixMods(missing); }); + action->setEnabled(true); + } + } + } + + QString deleteMenuLabel = tr("Delete %n save(s)", "", selection->selectedIndexes().count()); + + menu.addAction(deleteMenuLabel, [&]{ deleteSavegame(); }); + + menu.exec(ui.list->viewport()->mapToGlobal(pos)); +} + +void SavesTab::fixMods(SaveGameInfo::MissingAssets const &missingAssets) +{ + ActivateModsDialog dialog(missingAssets, m_window); + if (dialog.exec() == QDialog::Accepted) { + // activate the required mods, then enable all esps + std::set modsToActivate = dialog.getModsToActivate(); + for (std::set::iterator iter = modsToActivate.begin(); iter != modsToActivate.end(); ++iter) { + if ((*iter != "") && (*iter != "")) { + unsigned int modIndex = ModInfo::getIndex(*iter); + m_core.currentProfile()->setModEnabled(modIndex, true); + } + } + + m_core.currentProfile()->writeModlist(); + m_core.refreshLists(); + + std::set espsToActivate = dialog.getESPsToActivate(); + for (std::set::iterator iter = espsToActivate.begin(); iter != espsToActivate.end(); ++iter) { + m_core.pluginList()->enableESP(*iter); + } + + m_core.saveCurrentLists(); + } +} diff --git a/src/savestab.h b/src/savestab.h new file mode 100644 index 00000000..d3eb7e63 --- /dev/null +++ b/src/savestab.h @@ -0,0 +1,60 @@ +#ifndef MODORGANIZER_SAVESTAB_INCLUDED +#define MODORGANIZER_SAVESTAB_INCLUDED + +#include "savegameinfo.h" +#include + +namespace Ui { class MainWindow; } + +namespace MOBase +{ + class ISaveGame; + class ISaveGameInfoWidget; +} + +class MainWindow; +class OrganizerCore; + + +class SavesTab : public QObject +{ + Q_OBJECT; + +public: + SavesTab(QWidget* window, OrganizerCore& core, Ui::MainWindow* ui); + + void refreshSaveList(); + void displaySaveGameInfo(QListWidgetItem *newItem); + + QDir currentSavesDir() const; + + void startMonitorSaves(); + void stopMonitorSaves(); + void hideSaveGameInfo(); + +private: + struct SavesTabUi + { + QTabWidget* mainTabs; + QWidget* tab; + QListWidget* list; + }; + + QWidget* m_window; + OrganizerCore& m_core; + SavesTabUi ui; + MOBase::FilterWidget m_filter; + std::vector> m_SaveGames; + MOBase::ISaveGameInfoWidget *m_CurrentSaveView; + + QTimer m_SavesWatcherTimer; + QFileSystemWatcher m_SavesWatcher; + + void onContextMenu(const QPoint &pos); + void deleteSavegame(); + void saveSelectionChanged(QListWidgetItem *newItem); + void fixMods(SaveGameInfo::MissingAssets const &missingAssets); + void refreshSavesIfOpen(); +}; + +#endif // MODORGANIZER_SAVESTAB_INCLUDED -- cgit v1.3.1 From f46a14f3bfa0bec9decad453d967de089e4833ad Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 28 Dec 2020 05:37:14 -0500 Subject: delete shortcut for save games --- src/mainwindow.cpp | 5 +---- src/savestab.cpp | 18 ++++++++++++++++++ src/savestab.h | 3 +++ 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e7d99f23..0f5b15e3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1503,10 +1503,7 @@ void MainWindow::cleanup() bool MainWindow::eventFilter(QObject *object, QEvent *event) { - if ((object == ui->savegameList) && - ((event->type() == QEvent::Leave) || (event->type() == QEvent::WindowDeactivate))) { - m_SavesTab->hideSaveGameInfo(); - } else if (event->type() == QEvent::StatusTip && object != this) { + if (event->type() == QEvent::StatusTip && object != this) { QMainWindow::event(event); return true; } diff --git a/src/savestab.cpp b/src/savestab.cpp index a14321d3..31471740 100644 --- a/src/savestab.cpp +++ b/src/savestab.cpp @@ -32,6 +32,24 @@ SavesTab::SavesTab(QWidget* window, OrganizerCore& core, Ui::MainWindow* mwui) connect( ui.list, &QListWidget::itemEntered, [&](auto* item){ saveSelectionChanged(item); }); + + ui.list->installEventFilter(this); +} + +bool SavesTab::eventFilter(QObject* object, QEvent* e) +{ + if (object == ui.list) { + if (e->type() == QEvent::Leave || e->type() == QEvent::WindowDeactivate) { + hideSaveGameInfo(); + } else if (e->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(e); + if (keyEvent->key() == Qt::Key_Delete) { + deleteSavegame(); + } + } + } + + return false; } void SavesTab::displaySaveGameInfo(QListWidgetItem *newItem) diff --git a/src/savestab.h b/src/savestab.h index d3eb7e63..8d84e3c1 100644 --- a/src/savestab.h +++ b/src/savestab.h @@ -32,6 +32,9 @@ public: void stopMonitorSaves(); void hideSaveGameInfo(); +protected: + bool eventFilter(QObject* object, QEvent* e) override; + private: struct SavesTabUi { -- cgit v1.3.1