diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/aboutdialog.ui | 20 | ||||
| -rw-r--r-- | src/downloadlistview.cpp (renamed from src/downloadlistwidget.cpp) | 191 | ||||
| -rw-r--r-- | src/downloadlistview.h (renamed from src/downloadlistwidget.h) | 51 | ||||
| -rw-r--r-- | src/downloadstab.cpp | 8 | ||||
| -rw-r--r-- | src/downloadstab.h | 4 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 1 | ||||
| -rw-r--r-- | src/mainwindow.ui | 12 | ||||
| -rw-r--r-- | src/modlistcontextmenu.cpp | 48 | ||||
| -rw-r--r-- | src/modlistcontextmenu.h | 3 | ||||
| -rw-r--r-- | src/modlistversiondelegate.cpp | 8 | ||||
| -rw-r--r-- | src/modlistversiondelegate.h | 5 | ||||
| -rw-r--r-- | src/modlistview.cpp | 27 | ||||
| -rw-r--r-- | src/modlistview.h | 9 | ||||
| -rw-r--r-- | src/modlistviewactions.cpp | 17 | ||||
| -rw-r--r-- | src/modlistviewactions.h | 4 | ||||
| -rw-r--r-- | src/organizercore.cpp | 3 | ||||
| -rw-r--r-- | src/settings.cpp | 38 | ||||
| -rw-r--r-- | src/settings.h | 23 | ||||
| -rw-r--r-- | src/settingsdialog.ui | 208 | ||||
| -rw-r--r-- | src/settingsdialoguserinterface.cpp | 33 | ||||
| -rw-r--r-- | src/settingsdialoguserinterface.h | 6 | ||||
| -rw-r--r-- | src/shared/directoryentry.cpp | 14 |
23 files changed, 496 insertions, 239 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d1092637..a5d15740 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,7 +63,7 @@ add_filter(NAME src/dialogs GROUPS add_filter(NAME src/downloads GROUPS downloadlist - downloadlistwidget + downloadlistview downloadmanager ) diff --git a/src/aboutdialog.ui b/src/aboutdialog.ui index e1f7aef3..16fc57aa 100644 --- a/src/aboutdialog.ui +++ b/src/aboutdialog.ui @@ -220,6 +220,11 @@ <string notr="true">isa</string>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>Holt59</string>
+ </property>
+ </item>
</widget>
</item>
</layout>
@@ -256,11 +261,6 @@ <string notr="true">przester</string>
</property>
</item>
- <item>
- <property name="text">
- <string notr="true">Holt59</string>
- </property>
- </item>
</widget>
</item>
</layout>
@@ -491,6 +491,11 @@ </item>
<item>
<property name="text">
+ <string>Luca|EzioTheDeadPoet</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string notr="true">ogrotten</string>
</property>
</item>
@@ -501,6 +506,11 @@ </item>
<item>
<property name="text">
+ <string>Patchier</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string notr="true">PurpleFez</string>
</property>
</item>
diff --git a/src/downloadlistwidget.cpp b/src/downloadlistview.cpp index 22e3a3b9..a1f544a8 100644 --- a/src/downloadlistwidget.cpp +++ b/src/downloadlistview.cpp @@ -18,7 +18,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */
#include "downloadlist.h"
-#include "downloadlistwidget.h"
+#include "downloadlistview.h"
#include <report.h>
#include <log.h>
#include <QPainter>
@@ -34,7 +34,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. using namespace MOBase;
DownloadProgressDelegate::DownloadProgressDelegate(
- DownloadManager* manager, DownloadListWidget* list)
+ DownloadManager* manager, DownloadListView* list)
: QStyledItemDelegate(list), m_Manager(manager), m_List(list)
{
}
@@ -113,7 +113,7 @@ void DownloadListHeader::mouseReleaseEvent(QMouseEvent *event) customResizeSections();
}
-DownloadListWidget::DownloadListWidget(QWidget *parent)
+DownloadListView::DownloadListView(QWidget *parent)
: QTreeView(parent)
{
setHeader(new DownloadListHeader(Qt::Horizontal, this));
@@ -135,11 +135,11 @@ DownloadListWidget::DownloadListWidget(QWidget *parent) connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomContextMenu(QPoint)));
}
-DownloadListWidget::~DownloadListWidget()
+DownloadListView::~DownloadListView()
{
}
-void DownloadListWidget::setManager(DownloadManager *manager)
+void DownloadListView::setManager(DownloadManager *manager)
{
m_Manager = manager;
@@ -154,18 +154,18 @@ void DownloadListWidget::setManager(DownloadManager *manager) header()->hideSection(DownloadList::COL_SOURCEGAME);
}
-void DownloadListWidget::setSourceModel(DownloadList *sourceModel)
+void DownloadListView::setSourceModel(DownloadList *sourceModel)
{
m_SourceModel = sourceModel;
}
-void DownloadListWidget::setMetaDisplay(bool metaDisplay)
+void DownloadListView::setMetaDisplay(bool metaDisplay)
{
if (m_SourceModel != nullptr)
m_SourceModel->setMetaDisplay(metaDisplay);
}
-void DownloadListWidget::onDoubleClick(const QModelIndex &index)
+void DownloadListView::onDoubleClick(const QModelIndex &index)
{
QModelIndex sourceIndex = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(index);
if (m_Manager->getState(sourceIndex.row()) >= DownloadManager::STATE_READY)
@@ -175,7 +175,7 @@ void DownloadListWidget::onDoubleClick(const QModelIndex &index) emit resumeDownload(sourceIndex.row());
}
-void DownloadListWidget::onHeaderCustomContextMenu(const QPoint &point)
+void DownloadListView::onHeaderCustomContextMenu(const QPoint &point)
{
QMenu menu;
@@ -209,98 +209,133 @@ void DownloadListWidget::onHeaderCustomContextMenu(const QPoint &point) qobject_cast<DownloadListHeader*>(header())->customResizeSections();
}
-void DownloadListWidget::resizeEvent(QResizeEvent *event)
+void DownloadListView::resizeEvent(QResizeEvent *event)
{
QTreeView::resizeEvent(event);
qobject_cast<DownloadListHeader*>(header())->customResizeSections();
}
-void DownloadListWidget::onCustomContextMenu(const QPoint &point)
+void DownloadListView::onCustomContextMenu(const QPoint &point)
{
QMenu menu(this);
QModelIndex index = indexAt(point);
bool hidden = false;
- try
- {
+ try {
if (index.row() >= 0) {
- m_ContextRow = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(index).row();
- DownloadManager::DownloadState state = m_Manager->getState(m_ContextRow);
+ const int row = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(index).row();
+ DownloadManager::DownloadState state = m_Manager->getState(row);
- hidden = m_Manager->isHidden(m_ContextRow);
+ hidden = m_Manager->isHidden(row);
if (state >= DownloadManager::STATE_READY) {
- menu.addAction(tr("Install"), this, SLOT(issueInstall()));
- if (m_Manager->isInfoIncomplete(m_ContextRow))
- menu.addAction(tr("Query Info"), this, SLOT(issueQueryInfoMd5()));
+ menu.addAction(tr("Install"), [=] { issueInstall(row); });
+ if (m_Manager->isInfoIncomplete(row))
+ menu.addAction(tr("Query Info"), [=] { issueQueryInfoMd5(row); });
else
- menu.addAction(tr("Visit on Nexus"), this, SLOT(issueVisitOnNexus()));
- menu.addAction(tr("Open File"), this, SLOT(issueOpenFile()));
- menu.addAction(tr("Open Meta File"), this, SLOT(issueOpenMetaFile()));
- menu.addAction(tr("Reveal in Explorer"), this, SLOT(issueOpenInDownloadsFolder()));
+ menu.addAction(tr("Visit on Nexus"), [=] { issueVisitOnNexus(row); });
+ menu.addAction(tr("Open File"), [=] { issueOpenFile(row); });
+ menu.addAction(tr("Open Meta File"), [=] { issueOpenMetaFile(row); });
+ menu.addAction(tr("Reveal in Explorer"), [=] { issueOpenInDownloadsFolder(row); });
menu.addSeparator();
- menu.addAction(tr("Delete..."), this, SLOT(issueDelete()));
+ menu.addAction(tr("Delete..."), [=] { issueDelete(row); });
if (hidden)
- menu.addAction(tr("Un-Hide"), this, SLOT(issueRestoreToView()));
+ menu.addAction(tr("Un-Hide"), [=] { issueRestoreToView(row); });
else
- menu.addAction(tr("Hide"), this, SLOT(issueRemoveFromView()));
+ menu.addAction(tr("Hide"), [=] { issueRemoveFromView(row); });
} else if (state == DownloadManager::STATE_DOWNLOADING) {
- menu.addAction(tr("Cancel"), this, SLOT(issueCancel()));
- menu.addAction(tr("Pause"), this, SLOT(issuePause()));
- menu.addAction(tr("Reveal in Explorer"), this, SLOT(issueOpenInDownloadsFolder()));
- } else if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)
- || (state == DownloadManager::STATE_PAUSING)) {
- menu.addAction(tr("Delete..."), this, SLOT(issueDelete()));
- menu.addAction(tr("Resume"), this, SLOT(issueResume()));
- menu.addAction(tr("Reveal in Explorer"), this, SLOT(issueOpenInDownloadsFolder()));
+ menu.addAction(tr("Cancel"), [=] { issueCancel(row); });
+ menu.addAction(tr("Pause"), [=] { issuePause(row); });
+ menu.addAction(tr("Reveal in Explorer"), [=] { issueOpenInDownloadsFolder(row); });
+ }
+ else if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)
+ || (state == DownloadManager::STATE_PAUSING)) {
+ menu.addAction(tr("Delete..."), [=] { issueDelete(row); });
+ menu.addAction(tr("Resume"), [=] { issueResume(row); });
+ menu.addAction(tr("Reveal in Explorer"), [=] { issueOpenInDownloadsFolder(row); });
}
menu.addSeparator();
}
- } catch(std::exception&)
- {
+ }
+ catch(std::exception&) {
// this happens when the download index is not found, ignore it and don't
// display download-specific actions
}
- menu.addAction(tr("Delete Installed Downloads..."), this, SLOT(issueDeleteCompleted()));
- menu.addAction(tr("Delete Uninstalled Downloads..."), this, SLOT(issueDeleteUninstalled()));
- menu.addAction(tr("Delete All Downloads..."), this, SLOT(issueDeleteAll()));
+ menu.addAction(tr("Delete Installed Downloads..."), [=] { issueDeleteCompleted(); });
+ menu.addAction(tr("Delete Uninstalled Downloads..."), [=] { issueDeleteUninstalled(); });
+ menu.addAction(tr("Delete All Downloads..."), [=] { issueDeleteAll(); });
menu.addSeparator();
if (!hidden) {
- menu.addAction(tr("Hide Installed..."), this, SLOT(issueRemoveFromViewCompleted()));
- menu.addAction(tr("Hide Uninstalled..."), this, SLOT(issueRemoveFromViewUninstalled()));
- menu.addAction(tr("Hide All..."), this, SLOT(issueRemoveFromViewAll()));
+ menu.addAction(tr("Hide Installed..."), [=] { issueRemoveFromViewCompleted(); });
+ menu.addAction(tr("Hide Uninstalled..."), [=] { issueRemoveFromViewUninstalled(); });
+ menu.addAction(tr("Hide All..."), [=] { issueRemoveFromViewAll(); });
} else {
- menu.addAction(tr("Un-Hide All..."), this, SLOT(issueRestoreToViewAll()));
+ menu.addAction(tr("Un-Hide All..."), [=] { issueRestoreToViewAll(); } );
}
menu.exec(viewport()->mapToGlobal(point));
}
-void DownloadListWidget::issueInstall()
+void DownloadListView::keyPressEvent(QKeyEvent* event)
+{
+ if (selectionModel()->hasSelection()) {
+ const int row = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(currentIndex()).row();
+ auto state = m_Manager->getState(row);
+ if (state >= DownloadManager::STATE_READY) {
+ if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
+ issueInstall(row);
+ }
+ else if (event->key() == Qt::Key_Delete) {
+ issueDelete(row);
+ }
+ }
+ else if (state == DownloadManager::STATE_DOWNLOADING) {
+ if (event->key() == Qt::Key_Delete) {
+ issueCancel(row);
+ }
+ else if (event->key() == Qt::Key_Space) {
+ issuePause(event->key());
+ }
+ }
+ else if (state == DownloadManager::STATE_PAUSED
+ || state == DownloadManager::STATE_ERROR
+ || state == DownloadManager::STATE_PAUSING) {
+ if (event->key() == Qt::Key_Delete) {
+ issueDelete(row);
+ }
+ else if (event->key() == Qt::Key_Space) {
+ issueResume(row);
+ }
+ }
+ }
+ QTreeView::keyPressEvent(event);
+}
+
+void DownloadListView::issueInstall(int index)
{
- emit installDownload(m_ContextRow);
+ emit installDownload(index);
}
-void DownloadListWidget::issueQueryInfo()
+void DownloadListView::issueQueryInfo(int index)
{
- emit queryInfo(m_ContextRow);
+ emit queryInfo(index);
}
-void DownloadListWidget::issueQueryInfoMd5()
+void DownloadListView::issueQueryInfoMd5(int index)
{
- emit queryInfoMd5(m_ContextRow);
+ emit queryInfoMd5(index);
}
-void DownloadListWidget::issueDelete()
+void DownloadListView::issueDelete(int index)
{
const auto r = MOBase::TaskDialog(this, tr("Delete download"))
.main("Are you sure you want to delete this download?")
- .content(m_Manager->getFilePath(m_ContextRow))
+ .content(m_Manager->getFilePath(index))
.icon(QMessageBox::Question)
.button({tr("Move to the Recycle Bin"), QMessageBox::Yes})
.button({tr("Cancel"), QMessageBox::Cancel})
@@ -310,60 +345,60 @@ void DownloadListWidget::issueDelete() return;
}
- emit removeDownload(m_ContextRow, true);
+ emit removeDownload(index, true);
}
-void DownloadListWidget::issueRemoveFromView()
+void DownloadListView::issueRemoveFromView(int index)
{
- log::debug("removing from view: {}", m_ContextRow);
- emit removeDownload(m_ContextRow, false);
+ log::debug("removing from view: {}", index);
+ emit removeDownload(index, false);
}
-void DownloadListWidget::issueRestoreToView()
+void DownloadListView::issueRestoreToView(int index)
{
- emit restoreDownload(m_ContextRow);
+ emit restoreDownload(index);
}
-void DownloadListWidget::issueRestoreToViewAll()
+void DownloadListView::issueRestoreToViewAll()
{
emit restoreDownload(-1);
}
-void DownloadListWidget::issueVisitOnNexus()
+void DownloadListView::issueVisitOnNexus(int index)
{
- emit visitOnNexus(m_ContextRow);
+ emit visitOnNexus(index);
}
-void DownloadListWidget::issueOpenFile()
+void DownloadListView::issueOpenFile(int index)
{
- emit openFile(m_ContextRow);
+ emit openFile(index);
}
-void DownloadListWidget::issueOpenMetaFile() {
- emit openMetaFile(m_ContextRow);
+void DownloadListView::issueOpenMetaFile(int index) {
+ emit openMetaFile(index);
}
-void DownloadListWidget::issueOpenInDownloadsFolder()
+void DownloadListView::issueOpenInDownloadsFolder(int index)
{
- emit openInDownloadsFolder(m_ContextRow);
+ emit openInDownloadsFolder(index);
}
-void DownloadListWidget::issueCancel()
+void DownloadListView::issueCancel(int index)
{
- emit cancelDownload(m_ContextRow);
+ emit cancelDownload(index);
}
-void DownloadListWidget::issuePause()
+void DownloadListView::issuePause(int index)
{
- emit pauseDownload(m_ContextRow);
+ emit pauseDownload(index);
}
-void DownloadListWidget::issueResume()
+void DownloadListView::issueResume(int index)
{
- emit resumeDownload(m_ContextRow);
+ emit resumeDownload(index);
}
-void DownloadListWidget::issueDeleteAll()
+void DownloadListView::issueDeleteAll()
{
if (QMessageBox::warning(nullptr, tr("Delete Files?"),
tr("This will remove all finished downloads from this list and from disk.\n\nAre you absolutely sure you want to proceed?"),
@@ -372,7 +407,7 @@ void DownloadListWidget::issueDeleteAll() }
}
-void DownloadListWidget::issueDeleteCompleted()
+void DownloadListView::issueDeleteCompleted()
{
if (QMessageBox::warning(nullptr, tr("Delete Files?"),
tr("This will remove all installed downloads from this list and from disk.\n\nAre you absolutely sure you want to proceed?"),
@@ -381,7 +416,7 @@ void DownloadListWidget::issueDeleteCompleted() }
}
-void DownloadListWidget::issueDeleteUninstalled()
+void DownloadListView::issueDeleteUninstalled()
{
if (QMessageBox::warning(nullptr, tr("Delete Files?"),
tr("This will remove all uninstalled downloads from this list and from disk.\n\nAre you absolutely sure you want to proceed?"),
@@ -390,7 +425,7 @@ void DownloadListWidget::issueDeleteUninstalled() }
}
-void DownloadListWidget::issueRemoveFromViewAll()
+void DownloadListView::issueRemoveFromViewAll()
{
if (QMessageBox::question(nullptr, tr("Hide Files?"),
tr("This will remove all finished downloads from this list (but NOT from disk)."),
@@ -399,7 +434,7 @@ void DownloadListWidget::issueRemoveFromViewAll() }
}
-void DownloadListWidget::issueRemoveFromViewCompleted()
+void DownloadListView::issueRemoveFromViewCompleted()
{
if (QMessageBox::question(nullptr, tr("Hide Files?"),
tr("This will remove all installed downloads from this list (but NOT from disk)."),
@@ -408,7 +443,7 @@ void DownloadListWidget::issueRemoveFromViewCompleted() }
}
-void DownloadListWidget::issueRemoveFromViewUninstalled()
+void DownloadListView::issueRemoveFromViewUninstalled()
{
if (QMessageBox::question(nullptr, tr("Hide Files?"),
tr("This will remove all uninstalled downloads from this list (but NOT from disk)."),
diff --git a/src/downloadlistwidget.h b/src/downloadlistview.h index 64e1a6e8..050c869f 100644 --- a/src/downloadlistwidget.h +++ b/src/downloadlistview.h @@ -32,24 +32,24 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. namespace Ui {
- class DownloadListWidget;
+ class DownloadListView;
}
-class DownloadListWidget;
+class DownloadListView;
class DownloadProgressDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
- DownloadProgressDelegate(DownloadManager* manager, DownloadListWidget* list);
+ DownloadProgressDelegate(DownloadManager* manager, DownloadListView* list);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
private:
DownloadManager* m_Manager;
- DownloadListWidget* m_List;
+ DownloadListView* m_List;
};
class DownloadListHeader : public QHeaderView
@@ -64,13 +64,13 @@ private: void mouseReleaseEvent(QMouseEvent *event) override;
};
-class DownloadListWidget : public QTreeView
+class DownloadListView : public QTreeView
{
Q_OBJECT
public:
- explicit DownloadListWidget(QWidget *parent = 0);
- ~DownloadListWidget();
+ explicit DownloadListView(QWidget *parent = 0);
+ ~DownloadListView();
void setManager(DownloadManager *manager);
void setSourceModel(DownloadList *sourceModel);
@@ -90,35 +90,38 @@ signals: void openMetaFile(int index);
void openInDownloadsFolder(int index);
+protected:
+ void keyPressEvent(QKeyEvent* event) override;
+
private slots:
- void onDoubleClick(const QModelIndex &index);
- void onCustomContextMenu(const QPoint &point);
- void onHeaderCustomContextMenu(const QPoint &point);
- void issueInstall();
- void issueDelete();
- void issueRemoveFromView();
- void issueRestoreToView();
+ void onDoubleClick(const QModelIndex& index);
+ void onCustomContextMenu(const QPoint& point);
+ void onHeaderCustomContextMenu(const QPoint& point);
+
+ void issueInstall(int index);
+ void issueDelete(int index);
+ void issueRemoveFromView(int index);
+ void issueRestoreToView(int index);
void issueRestoreToViewAll();
- void issueVisitOnNexus();
- void issueOpenFile();
- void issueOpenMetaFile();
- void issueOpenInDownloadsFolder();
- void issueCancel();
- void issuePause();
- void issueResume();
+ void issueVisitOnNexus(int index);
+ void issueOpenFile(int index);
+ void issueOpenMetaFile(int index);
+ void issueOpenInDownloadsFolder(int index);
+ void issueCancel(int index);
+ void issuePause(int index);
+ void issueResume(int index);
void issueDeleteAll();
void issueDeleteCompleted();
void issueDeleteUninstalled();
void issueRemoveFromViewAll();
void issueRemoveFromViewCompleted();
void issueRemoveFromViewUninstalled();
- void issueQueryInfo();
- void issueQueryInfoMd5();
+ void issueQueryInfo(int index);
+ void issueQueryInfoMd5(int index);
private:
DownloadManager *m_Manager;
DownloadList *m_SourceModel = 0;
- int m_ContextRow;
void resizeEvent(QResizeEvent *event);
};
diff --git a/src/downloadstab.cpp b/src/downloadstab.cpp index a0602ede..ab7a1c9a 100644 --- a/src/downloadstab.cpp +++ b/src/downloadstab.cpp @@ -1,6 +1,6 @@ #include "downloadstab.h" #include "downloadlist.h" -#include "downloadlistwidget.h" +#include "downloadlistview.h" #include "organizercore.h" #include "ui_mainwindow.h" @@ -37,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, &DownloadListWidget::resumeDownload, [&](int i){ resumeDownload(i); }); + connect(ui.list, &DownloadListView::resumeDownload, [&](int i){ resumeDownload(i); }); } void DownloadsTab::update() @@ -50,10 +50,10 @@ void DownloadsTab::update() // 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; }"); + ui.list->setStyleSheet("DownloadListView::item { padding: 4px 2px; }"); } else { ui.list->setProperty("downloadView", "standard"); - ui.list->setStyleSheet("DownloadListWidget::item { padding: 16px 4px; }"); + ui.list->setStyleSheet("DownloadListView::item { padding: 16px 4px; }"); } ui.list->setMetaDisplay(m_core.settings().interface().metaDownloads()); diff --git a/src/downloadstab.h b/src/downloadstab.h index ac0cf0e2..f39f4ba5 100644 --- a/src/downloadstab.h +++ b/src/downloadstab.h @@ -5,7 +5,7 @@ namespace Ui { class MainWindow; } class OrganizerCore; -class DownloadListWidget; +class DownloadListView; class DownloadsTab : public QObject { @@ -20,7 +20,7 @@ private: struct DownloadsTabUi { QPushButton* refresh; - DownloadListWidget* list; + DownloadListView* list; QCheckBox* showHidden; QLineEdit* filter; }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c9824a24..9c049efa 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -46,7 +46,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "categoriesdialog.h" #include "overwriteinfodialog.h" #include "downloadlist.h" -#include "downloadlistwidget.h" #include "messagedialog.h" #include "installationmanager.h" #include "motddialog.h" diff --git a/src/mainwindow.ui b/src/mainwindow.ui index a0900542..4317b6c0 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1282,7 +1282,7 @@ p, li { white-space: pre-wrap; } <item> <layout class="QVBoxLayout" name="downloadLayout"> <item> - <widget class="DownloadListWidget" name="downloadView"> + <widget class="DownloadListView" name="downloadView"> <property name="minimumSize"> <size> <width>320</width> @@ -1942,11 +1942,6 @@ p, li { white-space: pre-wrap; } <header>lcdnumber.h</header> </customwidget> <customwidget> - <class>DownloadListWidget</class> - <extends>QTreeView</extends> - <header>downloadlistwidget.h</header> - </customwidget> - <customwidget> <class>MOBase::SortableTreeWidget</class> <extends>QWidget</extends> <header>sortabletreewidget.h</header> @@ -1961,6 +1956,11 @@ p, li { white-space: pre-wrap; } <extends>QStatusBar</extends> <header>statusbar.h</header> </customwidget> + <customwidget> + <class>DownloadListView</class> + <extends>QTreeView</extends> + <header>downloadlistview.h</header> + </customwidget> </customwidgets> <resources> <include location="resources.qrc"/> diff --git a/src/modlistcontextmenu.cpp b/src/modlistcontextmenu.cpp index 8bc73e40..f4aea109 100644 --- a/src/modlistcontextmenu.cpp +++ b/src/modlistcontextmenu.cpp @@ -17,20 +17,33 @@ ModListGlobalContextMenu::ModListGlobalContextMenu(OrganizerCore& core, ModListV ModListGlobalContextMenu::ModListGlobalContextMenu(OrganizerCore& core, ModListView* view, const QModelIndex& index, QWidget* parent) : QMenu(parent) { + connect(this, &QMenu::aboutToShow, [=, &core] { populate(core, view, index); }); +} + +void ModListGlobalContextMenu::populate(OrganizerCore& core, ModListView* view, const QModelIndex& index) +{ + clear(); + addAction(tr("Install Mod..."), [=]() { view->actions().installMod(); }); auto modIndex = index.data(ModList::IndexRole); - if (modIndex.isValid()) { + if (modIndex.isValid() && view->sortColumn() == ModList::COL_PRIORITY) { auto info = ModInfo::getByIndex(modIndex.toInt()); if (!info->isBackup()) { - addAction(info->isSeparator() ? tr("Create empty mod inside") : tr("Create empty mod before"), - [=]() { view->actions().createEmptyMod(index); }); - addAction(tr("Create separator before"), [=]() { view->actions().createSeparator(index); }); + QString text = tr("Create empty mod above"); + if (info->isSeparator()) { + text = tr("Create empty mod inside"); + } + else if (view->sortOrder() == Qt::DescendingOrder) { + text = tr("Create empty mod below"); + } + addAction(text, [=]() { view->actions().createEmptyMod(index); }); + addAction(tr("Create separator above"), [=]() { view->actions().createSeparator(index); }); } } else { - addAction(tr("Create empty mod at the end"), [=]() { view->actions().createEmptyMod(); }); - addAction(tr("Create separator at the end"), [=]() { view->actions().createSeparator(); }); + addAction(tr("Create empty mod"), [=]() { view->actions().createEmptyMod(); }); + addAction(tr("Create separator"), [=]() { view->actions().createSeparator(); }); } if (view->hasCollapsibleSeparators()) { @@ -41,18 +54,17 @@ ModListGlobalContextMenu::ModListGlobalContextMenu(OrganizerCore& core, ModListV addSeparator(); - addAction(tr("Enable all visible"), [=]() { - if (QMessageBox::question(view, tr("Confirm"), tr("Really enable all visible mods?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - view->enableAllVisible(); - } - }); - addAction(tr("Disable all visible"), [=]() { - if (QMessageBox::question(parent, tr("Confirm"), tr("Really disable all visible mods?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - view->disableAllVisible(); - } - }); + QString enableTxt = tr("Enable all"), + disableTxt = tr("Disable all"); + + if (view->isFilterActive()) { + enableTxt = tr("Enable all matching mods"); + disableTxt = tr("Disable all matching mods"); + } + + addAction(enableTxt, [=] { view->actions().setAllMatchingModsEnabled(true); }); + addAction(disableTxt, [=] { view->actions().setAllMatchingModsEnabled(false); }); + addAction(tr("Check for updates"), [=]() { view->actions().checkModsForUpdates(); }); addAction(tr("Refresh"), &core, &OrganizerCore::profileRefresh); addAction(tr("Export to csv..."), [=]() { view->actions().exportModListCSV(); }); diff --git a/src/modlistcontextmenu.h b/src/modlistcontextmenu.h index 2b3f9dcd..8a6ce3df 100644 --- a/src/modlistcontextmenu.h +++ b/src/modlistcontextmenu.h @@ -25,6 +25,9 @@ protected: friend class ModListContextMenu; + // populate the menu + void populate(OrganizerCore& core, ModListView* view, const QModelIndex& index); + // creates a "All mods" context menu for the given index (can be invalid). ModListGlobalContextMenu(OrganizerCore& core, ModListView* view, const QModelIndex& index, QWidget* parent = nullptr); diff --git a/src/modlistversiondelegate.cpp b/src/modlistversiondelegate.cpp index 657718f5..5ce574a5 100644 --- a/src/modlistversiondelegate.cpp +++ b/src/modlistversiondelegate.cpp @@ -1,10 +1,13 @@ #include "modlistversiondelegate.h" +#include "settings.h" #include "modlistview.h" #include "log.h" -ModListVersionDelegate::ModListVersionDelegate(ModListView* view) : - QItemDelegate(view), m_view(view) { } +ModListVersionDelegate::ModListVersionDelegate(ModListView* view, Settings& settings) : + QItemDelegate(view), m_view(view), m_settings(settings) +{ +} void ModListVersionDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const @@ -13,6 +16,7 @@ void ModListVersionDelegate::paint(QPainter* painter, const QStyleOptionViewItem if (m_view->hasCollapsibleSeparators() && m_view->model()->hasChildren(index) + && m_settings.interface().collapsibleSeparatorsIcons(ModList::COL_VERSION) && !m_view->isExpanded(index.sibling(index.row(), 0))) { auto* model = m_view->model(); diff --git a/src/modlistversiondelegate.h b/src/modlistversiondelegate.h index 8a51e9b4..d3d0ad3b 100644 --- a/src/modlistversiondelegate.h +++ b/src/modlistversiondelegate.h @@ -4,18 +4,19 @@ #include <QStyledItemDelegate> class ModListView; +class Settings; class ModListVersionDelegate : public QItemDelegate { public: - ModListVersionDelegate(ModListView* view); + ModListVersionDelegate(ModListView* view, Settings& settings); void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; private: - ModListView* m_view; + Settings& m_settings; }; #endif diff --git a/src/modlistview.cpp b/src/modlistview.cpp index 526e9c33..9b461b8f 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -213,6 +213,11 @@ Qt::SortOrder ModListView::sortOrder() const return m_sortProxy ? m_sortProxy->sortOrder() : Qt::AscendingOrder;
}
+bool ModListView::isFilterActive() const
+{
+ return m_sortProxy && m_sortProxy->isFilterActive();
+}
+
ModListView::GroupByMode ModListView::groupByMode() const
{
if (m_sortProxy == nullptr) {
@@ -294,16 +299,6 @@ std::optional<unsigned int> ModListView::prevMod(unsigned int modIndex) const return {};
}
-void ModListView::enableAllVisible()
-{
- m_core->modList()->setActive(indexViewToModel(flatIndex(model())), true);
-}
-
-void ModListView::disableAllVisible()
-{
- m_core->modList()->setActive(indexViewToModel(flatIndex(model())), false);
-}
-
void ModListView::setFilterCriteria(const std::vector<ModListSortProxy::Criteria>& criteria)
{
m_sortProxy->setCriteria(criteria);
@@ -800,7 +795,7 @@ void ModListView::setup(OrganizerCore& core, CategoryFactory& factory, MainWindo setItemDelegateForColumn(ModList::COL_FLAGS, new ModFlagIconDelegate(this, ModList::COL_FLAGS, 120));
setItemDelegateForColumn(ModList::COL_CONFLICTFLAGS, new ModConflictIconDelegate(this, ModList::COL_CONFLICTFLAGS, 80));
setItemDelegateForColumn(ModList::COL_CONTENT, new ModContentIconDelegate(this, ModList::COL_CONTENT, 150));
- setItemDelegateForColumn(ModList::COL_VERSION, new ModListVersionDelegate(this));
+ setItemDelegateForColumn(ModList::COL_VERSION, new ModListVersionDelegate(this, core.settings()));
if (m_core->settings().geometry().restoreState(header())) {
// hack: force the resize-signal to be triggered because restoreState doesn't seem to do that
@@ -1058,7 +1053,7 @@ void ModListView::refreshMarkersAndPlugins() {
QModelIndexList indexes = selectionModel()->selectedRows();
- if (m_core->settings().interface().collapsibleSeparatorsConflicts()) {
+ if (m_core->settings().interface().collapsibleSeparatorsHighlightFrom()) {
for (auto& idx : selectionModel()->selectedRows()) {
if (hasCollapsibleSeparators()
&& model()->hasChildren(idx)
@@ -1132,7 +1127,7 @@ QColor ModListView::markerColor(const QModelIndex& index) const // collapsed separator
auto rowIndex = index.sibling(index.row(), 0);
if (hasCollapsibleSeparators()
- && m_core->settings().interface().collapsibleSeparatorsConflicts()
+ && m_core->settings().interface().collapsibleSeparatorsHighlightTo()
&& model()->hasChildren(rowIndex) && !isExpanded(rowIndex)) {
std::vector<QColor> colors;
@@ -1169,7 +1164,7 @@ std::vector<ModInfo::EFlag> ModListView::modFlags(const QModelIndex& index, bool bool compact = false;
if (info->isSeparator()
&& hasCollapsibleSeparators()
- && m_core->settings().interface().collapsibleSeparatorsConflicts()
+ && m_core->settings().interface().collapsibleSeparatorsIcons(ModList::COL_FLAGS)
&& !isExpanded(index.sibling(index.row(), 0))) {
// combine the child conflicts
@@ -1200,7 +1195,7 @@ std::vector<ModInfo::EConflictFlag> ModListView::conflictFlags(const QModelIndex bool compact = false;
if (info->isSeparator()
&& hasCollapsibleSeparators()
- && m_core->settings().interface().collapsibleSeparatorsConflicts()
+ && m_core->settings().interface().collapsibleSeparatorsIcons(ModList::COL_CONFLICTFLAGS)
&& !isExpanded(index.sibling(index.row(), 0))) {
// combine the child conflicts
@@ -1235,7 +1230,7 @@ std::set<int> ModListView::contents(const QModelIndex& index, bool* includeChild if (info->isSeparator()
&& hasCollapsibleSeparators()
- && m_core->settings().interface().collapsibleSeparatorsConflicts()
+ && m_core->settings().interface().collapsibleSeparatorsIcons(ModList::COL_CONTENT)
&& !isExpanded(index.sibling(index.row(), 0))) {
// combine the child contents
diff --git a/src/modlistview.h b/src/modlistview.h index 39099cf7..adffd737 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -66,6 +66,10 @@ public: int sortColumn() const;
Qt::SortOrder sortOrder() const;
+ // check if a filter is currently active
+ //
+ bool isFilterActive() const;
+
// the current group mode
//
GroupByMode groupByMode() const;
@@ -108,11 +112,6 @@ signals: public slots:
- // enable/disable all visible mods
- //
- void enableAllVisible();
- void disableAllVisible();
-
// set the filter criteria/options for mods
//
void setFilterCriteria(const std::vector<ModListSortProxy::Criteria>& criteria);
diff --git a/src/modlistviewactions.cpp b/src/modlistviewactions.cpp index 03afa587..5af79b3b 100644 --- a/src/modlistviewactions.cpp +++ b/src/modlistviewactions.cpp @@ -17,6 +17,7 @@ #include "modinfodialog.h" #include "modlist.h" #include "modlistview.h" +#include "modelutils.h" #include "messagedialog.h" #include "nexusinterface.h" #include "nxmaccessmanager.h" @@ -172,6 +173,11 @@ void ModListViewActions::createSeparator(const QModelIndex& index) const int newPriority = -1; if (index.isValid() && m_view->sortColumn() == ModList::COL_PRIORITY) { newPriority = m_core.currentProfile()->getModPriority(index.data(ModList::IndexRole).toInt()); + + // descending order, we need to fix the priority + if (m_view->sortOrder() == Qt::DescendingOrder) { + newPriority++; + } } if (m_core.createMod(name) == nullptr) { @@ -192,6 +198,17 @@ void ModListViewActions::createSeparator(const QModelIndex& index) const m_view->scrollToAndSelect(m_view->indexModelToView(m_core.modList()->index(mIndex, 0))); } +void ModListViewActions::setAllMatchingModsEnabled(bool enabled) const +{ + const auto allIndex = m_view->indexViewToModel(flatIndex(m_view->model())); + const QString message = enabled ? + tr("Really enable %1 mod(s)?") : tr("Really disable %1 mod(s)?"); + if (QMessageBox::question(m_parent, tr("Confirm"), message.arg(allIndex.size()), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + m_core.modList()->setActive(allIndex, enabled); + } +} + void ModListViewActions::checkModsForUpdates() const { bool checkingModsForUpdate = false; diff --git a/src/modlistviewactions.h b/src/modlistviewactions.h index a3ae1b1a..3c225fbc 100644 --- a/src/modlistviewactions.h +++ b/src/modlistviewactions.h @@ -41,6 +41,10 @@ public: void createEmptyMod(const QModelIndex& index = QModelIndex()) const; void createSeparator(const QModelIndex& index = QModelIndex()) const; + // enable/disable all non-filtered mods + // + void setAllMatchingModsEnabled(bool enabled) const; + // check all mods for update // void checkModsForUpdates() const; diff --git a/src/organizercore.cpp b/src/organizercore.cpp index bbf6029b..e95aa565 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -808,6 +808,9 @@ ModInfo::Ptr OrganizerCore::installDownload(int index, int priority) reportError(tr("mod not found: %1").arg(qUtf8Printable(modName))); } m_DownloadManager.markInstalled(index); + if (settings().interface().hideDownloadsAfterInstallation()) { + m_DownloadManager.removeDownload(index, false); + } emit modInstalled(modName); return modInfo; } diff --git a/src/settings.cpp b/src/settings.cpp index d1f3ef4f..7047fa44 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2188,14 +2188,34 @@ void InterfaceSettings::setCollapsibleSeparators(bool ascending, bool descending set(m_Settings, "Settings", "collapsible_separators_dsc", descending); } -bool InterfaceSettings::collapsibleSeparatorsConflicts() const +bool InterfaceSettings::collapsibleSeparatorsHighlightTo() const { - return get<bool>(m_Settings, "Settings", "collapsible_separators_conflicts", true); + return get<bool>(m_Settings, "Settings", "collapsible_separators_conflicts_to", true); } -void InterfaceSettings::setCollapsibleSeparatorsConflicts(bool b) +void InterfaceSettings::setCollapsibleSeparatorsHighlightTo(bool b) { - set(m_Settings, "Settings", "collapsible_separators_conflicts", b); + set(m_Settings, "Settings", "collapsible_separators_conflicts_to", b); +} + +bool InterfaceSettings::collapsibleSeparatorsHighlightFrom() const +{ + return get<bool>(m_Settings, "Settings", "collapsible_separators_conflicts_from", true); +} + +void InterfaceSettings::setCollapsibleSeparatorsHighlightFrom(bool b) +{ + set(m_Settings, "Settings", "collapsible_separators_conflicts_from", b); +} + +bool InterfaceSettings::collapsibleSeparatorsIcons(int column) const +{ + return get<bool>(m_Settings, "Settings", QString("collapsible_separators_icons_%1").arg(column), true); +} + +void InterfaceSettings::setCollapsibleSeparatorsIcons(int column, bool show) +{ + set(m_Settings, "Settings", QString("collapsible_separators_icons_%1").arg(column), show); } bool InterfaceSettings::collapsibleSeparatorsPerProfile() const @@ -2238,6 +2258,16 @@ void InterfaceSettings::setMetaDownloads(bool b) set(m_Settings, "Settings", "meta_downloads", b); } +bool InterfaceSettings::hideDownloadsAfterInstallation() const +{ + return get<bool>(m_Settings, "Settings", "autohide_downloads", false); +} + +void InterfaceSettings::setHideDownloadsAfterInstallation(bool b) +{ + set(m_Settings, "Settings", "autohide_downloads", b); +} + bool InterfaceSettings::hideAPICounter() const { return get<bool>(m_Settings, "Settings", "hide_api_counter", false); diff --git a/src/settings.h b/src/settings.h index 484ce163..5f6dd37c 100644 --- a/src/settings.h +++ b/src/settings.h @@ -626,10 +626,22 @@ public: bool collapsibleSeparators(Qt::SortOrder order) const; void setCollapsibleSeparators(bool ascending, bool descending); - // whether to display mod conflicts on separators when collapsed + // whether to highlight mod conflicts and plugins on collapsed + // separators // - bool collapsibleSeparatorsConflicts() const; - void setCollapsibleSeparatorsConflicts(bool b); + bool collapsibleSeparatorsHighlightTo() const; + void setCollapsibleSeparatorsHighlightTo(bool b); + + // whether to highlight mod conflicts and plugins from separators + // when selected but collapsed + // + bool collapsibleSeparatorsHighlightFrom() const; + void setCollapsibleSeparatorsHighlightFrom(bool b); + + // whether to show icons on collapsed separators + // + bool collapsibleSeparatorsIcons(int column) const; + void setCollapsibleSeparatorsIcons(int column, bool show); // whether each profile should have its own expansion state // @@ -651,6 +663,11 @@ public: bool metaDownloads() const; void setMetaDownloads(bool b); + // whether to hide downloads after installing them + // + bool hideDownloadsAfterInstallation() const; + void setHideDownloadsAfterInstallation(bool b); + // whether the API counter should be hidden // bool hideAPICounter() const; diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index b23e6d90..bcef5d95 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -311,22 +311,16 @@ If you disable this feature, MO will only display official DLCs this way. Please <property name="checked"> <bool>false</bool> </property> - <layout class="QVBoxLayout" name="verticalLayout_20"> - <property name="leftMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>7</number> - </property> - <item> - <widget class="QWidget" name="widget_8" native="true"> + <layout class="QGridLayout" name="gridLayout_7"> + <item row="0" column="0"> + <widget class="QWidget" name="collapsibleSeparatorsWidget" native="true"> <property name="minimumSize"> <size> <width>0</width> - <height>0</height> + <height>50</height> </size> </property> - <layout class="QHBoxLayout" name="horizontalLayout_13"> + <layout class="QGridLayout" name="gridLayout_10"> <property name="leftMargin"> <number>0</number> </property> @@ -339,62 +333,139 @@ If you disable this feature, MO will only display official DLCs this way. Please <property name="bottomMargin"> <number>0</number> </property> - <item> - <widget class="QLabel" name="label_18"> - <property name="text"> - <string>When sorting by</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="collapsibleSeparatorsAscBox"> - <property name="text"> - <string>ascending priority</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="collapsibleSeparatorsDscBox"> - <property name="text"> - <string>descending priority</string> + <item row="0" column="0"> + <layout class="QGridLayout" name="gridLayout_9"> + <property name="verticalSpacing"> + <number>9</number> </property> - </widget> + <item row="0" column="0"> + <widget class="QLabel" name="collapsibleSeparatorsLabel"> + <property name="text"> + <string>When sorting by</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_35"> + <property name="text"> + <string>Show icons on separators</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QCheckBox" name="collapsibleSeparatorsPerProfileBox"> + <property name="toolTip"> + <string>Do not share the collapse/expanded state of separators between profiles.</string> + </property> + <property name="whatsThis"> + <string>Do not share the collapse/expanded state of separators between profiles.</string> + </property> + <property name="text"> + <string>Profile-specific collapse states for separators</string> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QCheckBox" name="collapsibleSeparatorsIconsFlagsBox"> + <property name="text"> + <string>flags</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_34"> + <property name="text"> + <string>Show conflicts and plugins </string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="collapsibleSeparatorsIconsConflictsBox"> + <property name="text"> + <string>conflicts</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="3"> + <widget class="QCheckBox" name="collapsibleSeparatorsIconsContentsBox"> + <property name="text"> + <string>content</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="4"> + <widget class="QCheckBox" name="collapsibleSeparatorsIconsVersionBox"> + <property name="text"> + <string>version</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QCheckBox" name="collapsibleSeparatorsAscBox"> + <property name="text"> + <string>ascending priority</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="3" colspan="2"> + <widget class="QCheckBox" name="collapsibleSeparatorsDscBox"> + <property name="text"> + <string>descending priority</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="QCheckBox" name="collapsibleSeparatorsHighlightToBox"> + <property name="toolTip"> + <string>Highlight collapsed separators based on conflicts and plugins from mods inside them.</string> + </property> + <property name="whatsThis"> + <string>Highlight collapsed separators based on conflicts and plugins from mods inside them.</string> + </property> + <property name="text"> + <string>on separators</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="3" colspan="2"> + <widget class="QCheckBox" name="collapsibleSeparatorsHighlightFromBox"> + <property name="toolTip"> + <string>When selecting a collapsed separator, highlight conflicting mods and plugins from mods inside the separator.</string> + </property> + <property name="whatsThis"> + <string>When selecting a collapsed separator, highlight conflicting mods and plugins from mods inside the separator.</string> + </property> + <property name="text"> + <string>from separators</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> </item> </layout> </widget> </item> - <item> - <widget class="QCheckBox" name="collapsibleSeparatorsConflictsBox"> - <property name="toolTip"> - <string>Display mod conflicts on and from separator when collapsed, and show plugins from collapsed separators.</string> - </property> - <property name="whatsThis"> - <string>Display mod conflicts on and from separator when collapsed, and show plugins from collapsed separators.</string> - </property> - <property name="text"> - <string>Show conflicts and plugins on separators and from separators</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="collapsibleSeparatorsPerProfileBox"> - <property name="toolTip"> - <string>Do not share the collapse/expanded state of separators between profiles.</string> - </property> - <property name="whatsThis"> - <string>Do not share the collapse/expanded state of separators between profiles.</string> - </property> - <property name="text"> - <string>Profile-specific collapse states for separators</string> - </property> - </widget> - </item> </layout> </widget> </item> @@ -450,6 +521,19 @@ If you disable this feature, MO will only display official DLCs this way. Please </widget> </item> <item> + <widget class="QCheckBox" name="hideDownloadInstallBox"> + <property name="toolTip"> + <string>Automatically hide downloads after successful installation.</string> + </property> + <property name="whatsThis"> + <string>Automatically hide downloads after successful installation.</string> + </property> + <property name="text"> + <string>Hide downloads after installation</string> + </property> + </widget> + </item> + <item> <spacer name="verticalSpacer_5"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/src/settingsdialoguserinterface.cpp b/src/settingsdialoguserinterface.cpp index cdd30f2e..49710771 100644 --- a/src/settingsdialoguserinterface.cpp +++ b/src/settingsdialoguserinterface.cpp @@ -3,13 +3,20 @@ #include "shared/appconfig.h" #include "categoriesdialog.h" #include "colortable.h" +#include "modlist.h" #include <utility.h> #include <questionboxmemory.h> using namespace MOBase; UserInterfaceSettingsTab::UserInterfaceSettingsTab(Settings& s, SettingsDialog& d) - : SettingsTab(s, d) + : SettingsTab(s, d), + m_columnToBox{ + { ModList::COL_CONFLICTFLAGS, ui->collapsibleSeparatorsIconsConflictsBox }, + { ModList::COL_FLAGS, ui->collapsibleSeparatorsIconsFlagsBox }, + { ModList::COL_CONTENT, ui->collapsibleSeparatorsIconsContentsBox}, + { ModList::COL_VERSION, ui->collapsibleSeparatorsIconsVersionBox } + } { // connect before setting to trigger @@ -19,15 +26,21 @@ UserInterfaceSettingsTab::UserInterfaceSettingsTab(Settings& s, SettingsDialog& // mod list ui->displayForeignBox->setChecked(settings().interface().displayForeign()); ui->colorSeparatorsBox->setChecked(settings().colors().colorSeparatorScrollbar()); - ui->collapsibleSeparatorsConflictsBox->setChecked(settings().interface().collapsibleSeparatorsConflicts()); ui->collapsibleSeparatorsAscBox->setChecked(settings().interface().collapsibleSeparators(Qt::AscendingOrder)); ui->collapsibleSeparatorsDscBox->setChecked(settings().interface().collapsibleSeparators(Qt::DescendingOrder)); + ui->collapsibleSeparatorsHighlightFromBox->setChecked(settings().interface().collapsibleSeparatorsHighlightFrom()); + ui->collapsibleSeparatorsHighlightToBox->setChecked(settings().interface().collapsibleSeparatorsHighlightTo()); ui->collapsibleSeparatorsPerProfileBox->setChecked(settings().interface().collapsibleSeparatorsPerProfile()); ui->saveFiltersBox->setChecked(settings().interface().saveFilters()); + for (auto& p : m_columnToBox) { + p.second->setChecked(settings().interface().collapsibleSeparatorsIcons(p.first)); + } + // download list ui->compactBox->setChecked(settings().interface().compactDownloads()); ui->showMetaBox->setChecked(settings().interface().metaDownloads()); + ui->hideDownloadInstallBox->setChecked(settings().interface().hideDownloadsAfterInstallation()); // colors ui->colorTable->load(s); @@ -43,13 +56,19 @@ void UserInterfaceSettingsTab::update() settings().interface().setDisplayForeign(ui->displayForeignBox->isChecked()); settings().interface().setCollapsibleSeparators( ui->collapsibleSeparatorsAscBox->isChecked(), ui->collapsibleSeparatorsDscBox->isChecked()); - settings().interface().setCollapsibleSeparatorsConflicts(ui->collapsibleSeparatorsConflictsBox->isChecked()); + settings().interface().setCollapsibleSeparatorsHighlightFrom(ui->collapsibleSeparatorsHighlightFromBox->isChecked()); + settings().interface().setCollapsibleSeparatorsHighlightTo(ui->collapsibleSeparatorsHighlightToBox->isChecked()); settings().interface().setCollapsibleSeparatorsPerProfile(ui->collapsibleSeparatorsPerProfileBox->isChecked()); settings().interface().setSaveFilters(ui->saveFiltersBox->isChecked()); + for (auto& p : m_columnToBox) { + settings().interface().setCollapsibleSeparatorsIcons(p.first, p.second->isChecked()); + } + // download list settings().interface().setCompactDownloads(ui->compactBox->isChecked()); settings().interface().setMetaDownloads(ui->showMetaBox->isChecked()); + settings().interface().setHideDownloadsAfterInstallation(ui->hideDownloadInstallBox->isChecked()); // colors ui->colorTable->commitColors(); @@ -59,6 +78,10 @@ void UserInterfaceSettingsTab::updateCollapsibleSeparatorsGroup() { const auto checked = ui->collapsibleSeparatorsAscBox->isChecked() || ui->collapsibleSeparatorsDscBox->isChecked(); - ui->collapsibleSeparatorsConflictsBox->setEnabled(checked); - ui->collapsibleSeparatorsPerProfileBox->setEnabled(checked); + for (auto* widget : ui->collapsibleSeparatorsWidget->findChildren<QWidget*>()) { + widget->setEnabled(checked); + } + ui->collapsibleSeparatorsLabel->setEnabled(true); + ui->collapsibleSeparatorsAscBox->setEnabled(true); + ui->collapsibleSeparatorsDscBox->setEnabled(true); } diff --git a/src/settingsdialoguserinterface.h b/src/settingsdialoguserinterface.h index 4609ae54..0c3c7fb7 100644 --- a/src/settingsdialoguserinterface.h +++ b/src/settingsdialoguserinterface.h @@ -1,6 +1,8 @@ #ifndef SETTINGSDIALOGUSERINTERFACE_H #define SETTINGSDIALOGUSERINTERFACE_H +#include <QCheckBox> + #include "settingsdialog.h" #include "settings.h" @@ -16,6 +18,10 @@ protected slots: // enable/disable the collapsible separators group depending on // the checkbox states void updateCollapsibleSeparatorsGroup(); + +private: + + const std::map<int, QCheckBox*> m_columnToBox; }; #endif // SETTINGSDIALOGGENERAL_H diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 0d275844..badb5636 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -211,7 +211,19 @@ void DirectoryEntry::addFromBSA( }
BSA::Archive archive;
- BSA::EErrorCode res = archive.read(ToString(archivePath, false).c_str(), false);
+ BSA::EErrorCode res = BSA::ERROR_NONE;
+
+ try
+ {
+ // read() can return an error, but it can also throw if the file is not a
+ // valid bsa
+ res = archive.read(ToString(archivePath, false).c_str(), false);
+ }
+ catch(std::exception& e)
+ {
+ log::error("invalid bsa '{}', error {}", archivePath, e.what());
+ return;
+ }
if ((res != BSA::ERROR_NONE) && (res != BSA::ERROR_INVALIDHASHES)) {
log::error("invalid bsa '{}', error {}", archivePath, res);
|
