feat: Column on left, hideable

- columns are hideable (saves to settings)
- image column moved to left
- datamodals can provide resize modes

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers 2023-05-24 20:15:34 -07:00
parent 74e7c13a17
commit 086a7e19f0
13 changed files with 131 additions and 9 deletions

View File

@ -37,6 +37,7 @@
#include "ModFolderModel.h"
#include <FileSystem.h>
#include <qheaderview.h>
#include <QDebug>
#include <QFileSystemWatcher>
#include <QIcon>
@ -56,7 +57,8 @@
ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance, bool is_indexed, bool create_dir)
: ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed)
{
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER, SortType::NAME };
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER};
m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents};
}
QVariant ModFolderModel::data(const QModelIndex &index, int role) const
@ -143,7 +145,7 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
switch (section)
{
case ActiveColumn:
return QString();
return tr("Enable");
case NameColumn:
return tr("Name");
case VersionColumn:

View File

@ -64,11 +64,11 @@ public:
enum Columns
{
ActiveColumn = 0,
ImageColumn,
NameColumn,
VersionColumn,
DateColumn,
ProviderColumn,
ImageColumn,
NUM_COLUMNS
};
enum ModStatusAction {
@ -78,6 +78,8 @@ public:
};
ModFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance, bool is_indexed = false, bool create_dir = true);
virtual QString id() const override { return "mods"; }
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

View File

@ -8,12 +8,15 @@
#include <QStyle>
#include <QThreadPool>
#include <QUrl>
#include <QMenu>
#include "Application.h"
#include "FileSystem.h"
#include "QVariantUtils.h"
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
#include "settings/Setting.h"
#include "tasks/Task.h"
ResourceFolderModel::ResourceFolderModel(QDir dir, std::shared_ptr<const BaseInstance> instance, QObject* parent, bool create_dir)
@ -471,6 +474,8 @@ QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientatio
switch (role) {
case Qt::DisplayRole:
switch (section) {
case ACTIVE_COLUMN:
return tr("Enable");
case NAME_COLUMN:
return tr("Name");
case DATE_COLUMN:
@ -500,6 +505,67 @@ QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientatio
return {};
}
void ResourceFolderModel::setupHeaderAction(QAction* act, int column)
{
Q_ASSERT(act);
act->setText(headerData(column, Qt::Orientation::Horizontal).toString());
}
void ResourceFolderModel::saveHiddenColumn(int column, bool hidden)
{
auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id());
auto setting = (APPLICATION->settings()->contains(setting_name)) ?
APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name);
auto hiddenColumns = QVariantUtils::toList<int>(setting->get());
auto index = hiddenColumns.indexOf(column);
if (index >= 0 && !hidden) {
hiddenColumns.removeAt(index);
} else if ( index < 0 && hidden) {
hiddenColumns.append(column);
}
setting->set(QVariantUtils::fromList(hiddenColumns));
}
void ResourceFolderModel::loadHiddenColumns(QTreeView *tree)
{
auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id());
auto setting = (APPLICATION->settings()->contains(setting_name)) ?
APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name);
auto hiddenColumns = QVariantUtils::toList<int>(setting->get().toList());
for (auto col : hiddenColumns) {
tree->setColumnHidden(col, true);
}
}
std::unique_ptr<QMenu> ResourceFolderModel::createHeaderContextMenu(QWidget* parent, QTreeView* tree)
{
auto menu = std::make_unique<QMenu>(parent);
menu->addSeparator()->setText(tr("Show / Hide Columns"));
for (int col = 0; col < columnCount(); ++col) {
auto act = new QAction();
setupHeaderAction(act, col);
act->setCheckable(true);
act->setChecked(!tree->isColumnHidden(col));
connect(act, &QAction::toggled, tree, [this, col, tree](bool toggled){
tree->setColumnHidden(col, !toggled);
saveHiddenColumn(col, !toggled);
});
menu->addAction(act);
}
return menu;
}
QSortFilterProxyModel* ResourceFolderModel::createFilterProxyModel(QObject* parent)
{
return new ProxyModel(parent);

View File

@ -1,5 +1,8 @@
#pragma once
#include <QHeaderView>
#include <QAction>
#include <QTreeView>
#include <QAbstractListModel>
#include <QDir>
#include <QFileSystemWatcher>
@ -29,6 +32,8 @@ class ResourceFolderModel : public QAbstractListModel {
ResourceFolderModel(QDir, std::shared_ptr<const BaseInstance>, QObject* parent = nullptr, bool create_dir = true);
~ResourceFolderModel() override;
virtual QString id() const { return "resource"; }
/** Starts watching the paths for changes.
*
* Returns whether starting to watch all the paths was successful.
@ -110,6 +115,11 @@ class ResourceFolderModel : public QAbstractListModel {
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
void setupHeaderAction(QAction* act, int column);
void saveHiddenColumn(int column, bool hidden);
void loadHiddenColumns(QTreeView* tree);
std::unique_ptr<QMenu> createHeaderContextMenu(QWidget* parent, QTreeView* tree);
/** This creates a proxy model to filter / sort the model for a UI.
*
* The actual comparisons and filtering are done directly by the Resource, so to modify behavior go there instead!
@ -117,6 +127,7 @@ class ResourceFolderModel : public QAbstractListModel {
QSortFilterProxyModel* createFilterProxyModel(QObject* parent = nullptr);
[[nodiscard]] SortType columnToSortKey(size_t column) const;
[[nodiscard]] QList<QHeaderView::ResizeMode> columnResizeModes() const { return m_column_resize_modes; }
class ProxyModel : public QSortFilterProxyModel {
public:
@ -187,6 +198,7 @@ class ResourceFolderModel : public QAbstractListModel {
// Represents the relationship between a column's index (represented by the list index), and it's sorting key.
// As such, the order in with they appear is very important!
QList<SortType> m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE };
QList<QHeaderView::ResizeMode> m_column_resize_modes = { QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents };
bool m_can_interact = true;

View File

@ -50,7 +50,9 @@
ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
: ResourceFolderModel(QDir(dir), instance)
{
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE, SortType::NAME };
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE};
m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents};
}
QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
@ -130,7 +132,7 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient
case Qt::DisplayRole:
switch (section) {
case ActiveColumn:
return QString();
return tr("Enable");
case NameColumn:
return tr("Name");
case PackFormatColumn:

View File

@ -11,15 +11,17 @@ public:
enum Columns
{
ActiveColumn = 0,
ImageColumn,
NameColumn,
PackFormatColumn,
DateColumn,
ImageColumn,
NUM_COLUMNS
};
explicit ResourcePackFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance);
virtual QString id() const override { return "resourcepacks"; }
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

View File

@ -9,4 +9,6 @@ class ShaderPackFolderModel : public ResourceFolderModel {
explicit ShaderPackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
: ResourceFolderModel(QDir(dir), instance)
{}
virtual QString id() const override { return "shaderpacks"; }
};

View File

@ -45,7 +45,9 @@
TexturePackFolderModel::TexturePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
: ResourceFolderModel(QDir(dir), instance)
{
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE, SortType::NAME };
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE };
m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents};
}
Task* TexturePackFolderModel::createUpdateTask()
@ -115,6 +117,8 @@ QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orienta
switch (role) {
case Qt::DisplayRole:
switch (section) {
case ActiveColumn:
return tr("Enable");
case NameColumn:
return tr("Name");
case DateColumn:
@ -149,4 +153,5 @@ QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orienta
int TexturePackFolderModel::columnCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : NUM_COLUMNS;
}
}

View File

@ -49,14 +49,16 @@ public:
enum Columns
{
ActiveColumn = 0,
ImageColumn,
NameColumn,
DateColumn,
ImageColumn,
NUM_COLUMNS
};
explicit TexturePackFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance);
virtual QString id() const override { return "texturepacks"; }
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

View File

@ -24,6 +24,8 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared
m_filterModel->setSourceModel(m_model.get());
m_filterModel->setFilterKeyColumn(-1);
ui->treeView->setModel(m_filterModel);
// must come after setModel
ui->treeView->setResizeModes(m_model->columnResizeModes());
ui->treeView->installEventFilter(this);
ui->treeView->sortByColumn(1, Qt::AscendingOrder);
@ -44,6 +46,13 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared
auto selection_model = ui->treeView->selectionModel();
connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current);
connect(ui->filterEdit, &QLineEdit::textChanged, this, &ExternalResourcesPage::filterTextChanged);
auto viewHeader = ui->treeView->header();
viewHeader->setContextMenuPolicy(Qt::CustomContextMenu);
connect(viewHeader, &QHeaderView::customContextMenuRequested, this, &ExternalResourcesPage::ShowHeaderContextMenu);
m_model->loadHiddenColumns(ui->treeView);
}
ExternalResourcesPage::~ExternalResourcesPage()
@ -65,6 +74,12 @@ void ExternalResourcesPage::ShowContextMenu(const QPoint& pos)
delete menu;
}
void ExternalResourcesPage::ShowHeaderContextMenu(const QPoint& pos)
{
auto menu = m_model->createHeaderContextMenu(this, ui->treeView);
menu->exec(ui->treeView->mapToGlobal(pos));
}
void ExternalResourcesPage::openedImpl()
{
m_model->startWatching();

View File

@ -60,6 +60,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage {
virtual void viewConfigs();
void ShowContextMenu(const QPoint& pos);
void ShowHeaderContextMenu(const QPoint& pos);
protected:
BaseInstance* m_instance = nullptr;

View File

@ -79,3 +79,12 @@ void ModListView::setModel ( QAbstractItemModel* model )
});
}
}
void ModListView::setResizeModes(const QList<QHeaderView::ResizeMode> &modes)
{
auto head = header();
for(int i = 0; i < modes.count(); i++) {
head->setSectionResizeMode(i, modes[i]);
}
}

View File

@ -14,6 +14,7 @@
*/
#pragma once
#include <QHeaderView>
#include <QTreeView>
class ModListView: public QTreeView
@ -22,4 +23,5 @@ class ModListView: public QTreeView
public:
explicit ModListView ( QWidget* parent = 0 );
virtual void setModel ( QAbstractItemModel* model );
virtual void setResizeModes (const QList<QHeaderView::ResizeMode>& modes);
};