summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-06-25 10:16:12 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2019-07-02 10:10:18 -0400
commitb6d8f4e479e42e401be60f522a0496c1f5624089 (patch)
treef044bb2b8cad55bbd940e1d2dce207fd0d4f8da9 /src
parent9e3214a73a5cc38a9b4f0313d8a48c0374cb57a3 (diff)
custom models for esp lists
Diffstat (limited to 'src')
-rw-r--r--src/modinfodialog.ui4
-rw-r--r--src/modinfodialogconflicts.cpp2
-rw-r--r--src/modinfodialogesps.cpp245
-rw-r--r--src/modinfodialogesps.h9
-rw-r--r--src/modinfodialogtextfiles.cpp3
5 files changed, 184 insertions, 79 deletions
diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui
index bcdf1007..a152c292 100644
--- a/src/modinfodialog.ui
+++ b/src/modinfodialog.ui
@@ -244,7 +244,7 @@
</widget>
</item>
<item>
- <widget class="QListWidget" name="inactiveESPList">
+ <widget class="QListView" name="inactiveESPList">
<property name="toolTip">
<string>List of esps, esms, and esls that can not be loaded by the game.</string>
</property>
@@ -374,7 +374,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e
</widget>
</item>
<item>
- <widget class="QListWidget" name="activeESPList">
+ <widget class="QListView" name="activeESPList">
<property name="toolTip">
<string>ESPs in the data directory and thus visible to the game.</string>
</property>
diff --git a/src/modinfodialogconflicts.cpp b/src/modinfodialogconflicts.cpp
index 05b69f05..03589030 100644
--- a/src/modinfodialogconflicts.cpp
+++ b/src/modinfodialogconflicts.cpp
@@ -135,6 +135,7 @@ public:
void clear()
{
m_items.clear();
+ endResetModel();
}
void reserve(std::size_t s)
@@ -261,7 +262,6 @@ public:
void finished()
{
- beginResetModel();
endResetModel();
}
diff --git a/src/modinfodialogesps.cpp b/src/modinfodialogesps.cpp
index 6c4fc4dd..3f742bae 100644
--- a/src/modinfodialogesps.cpp
+++ b/src/modinfodialogesps.cpp
@@ -1,13 +1,14 @@
#include "modinfodialogesps.h"
#include "ui_modinfodialog.h"
+#include "modinfodialog.h"
#include <report.h>
using MOBase::reportError;
-class ESP
+class ESPItem
{
public:
- ESP(QString rootPath, QString relativePath)
+ ESPItem(QString rootPath, QString relativePath)
: m_rootPath(std::move(rootPath)), m_active(false)
{
if (relativePath.contains('/')) {
@@ -16,6 +17,8 @@ public:
m_activePath = relativePath;
m_active = true;
}
+
+ updateFilename();
}
const QString& rootPath() const
@@ -32,6 +35,11 @@ public:
}
}
+ const QString& filename() const
+ {
+ return m_filename;
+ }
+
const QString& activePath() const
{
return m_activePath;
@@ -65,6 +73,8 @@ public:
m_inactivePath = QFileInfo(m_inactivePath).path() + QDir::separator() + newName;
}
+ updateFilename();
+
return true;
}
@@ -78,6 +88,7 @@ public:
if (root.rename(m_activePath, newName)) {
m_active = false;
m_inactivePath = newName;
+ updateFilename();
return true;
}
@@ -88,45 +99,137 @@ private:
QString m_rootPath;
QString m_activePath;
QString m_inactivePath;
+ QString m_filename;
bool m_active;
+
+ void updateFilename()
+ {
+ m_filename = fileInfo().fileName();
+ }
};
-class ESPItem : public QListWidgetItem
+class ESPListModel : public QAbstractItemModel
{
public:
- ESPItem(ESP esp)
- : m_esp(std::move(esp))
+ void clear()
{
- updateText();
+ m_esps.clear();
+ endResetModel();
}
- const ESP& esp() const
+ QModelIndex index(int row, int col, const QModelIndex& ={}) const override
{
- return m_esp;
+ return createIndex(row, col);
}
- void setESP(ESP esp)
+ QModelIndex parent(const QModelIndex&) const override
{
- m_esp = esp;
- updateText();
+ return {};
}
-private:
- ESP m_esp;
+ int rowCount(const QModelIndex& ={}) const override
+ {
+ return static_cast<int>(m_esps.size());
+ }
+
+ int columnCount(const QModelIndex& ={}) const override
+ {
+ return 1;
+ }
+
+ QVariant data(const QModelIndex& index, int role) const override
+ {
+ if (role == Qt::DisplayRole) {
+ if (auto* esp=getESP(index)) {
+ return esp->filename();
+ }
+ }
+
+ return {};
+ }
+
+
+ void add(ESPItem esp)
+ {
+ m_esps.emplace_back(std::move(esp));
+ }
+
+ void addOne(ESPItem esp)
+ {
+ const auto i = m_esps.size();
+
+ beginInsertRows({}, static_cast<int>(i), static_cast<int>(i));
+ add(std::move(esp));
+ endInsertRows();
+ }
+
+ bool removeRows(int row, int count, const QModelIndex& = {}) override
+ {
+ if (row < 0) {
+ return false;
+ }
+
+ const auto start = static_cast<std::size_t>(row);
+ if (start >= m_esps.size()) {
+ return false;
+ }
+
+ const auto end = std::min(
+ start + static_cast<std::size_t>(count),
+ m_esps.size());
+
+ beginRemoveRows({}, static_cast<int>(start), static_cast<int>(end));
+ m_esps.erase(m_esps.begin() + start, m_esps.begin() + end);
+ endRemoveRows();
+
+ return true;
+ }
- void updateText()
+ void finished()
{
- setText(m_esp.fileInfo().fileName());
+ std::sort(m_esps.begin(), m_esps.end(), [](const auto& a, const auto& b) {
+ return (naturalCompare(a.filename(), b.filename()) < 0);
+ });
+
+ endResetModel();
+ }
+
+ const ESPItem* getESP(const QModelIndex& index) const
+ {
+ const auto row = index.row();
+ if (row < 0) {
+ return nullptr;
+ }
+
+ const auto i = static_cast<std::size_t>(row);
+ if (i >= m_esps.size()) {
+ return nullptr;
+ }
+
+ return &m_esps[i];
}
+
+ ESPItem* getESP(const QModelIndex& index)
+ {
+ return const_cast<ESPItem*>(std::as_const(*this).getESP(index));
+ }
+
+private:
+ std::deque<ESPItem> m_esps;
};
+
ESPsTab::ESPsTab(
OrganizerCore& oc, PluginContainer& plugin,
- QWidget* parent, Ui::ModInfoDialog* ui, int id)
- : ModInfoDialogTab(oc, plugin, parent, ui, id)
+ QWidget* parent, Ui::ModInfoDialog* ui, int id) :
+ ModInfoDialogTab(oc, plugin, parent, ui, id),
+ m_inactiveModel(new ESPListModel), m_activeModel(new ESPListModel)
{
+ ui->inactiveESPList->setModel(m_inactiveModel);
+ ui->activeESPList->setModel(m_activeModel);
+
QObject::connect(
ui->activateESP, &QToolButton::clicked, [&]{ onActivate(); });
@@ -136,8 +239,8 @@ ESPsTab::ESPsTab(
void ESPsTab::clear()
{
- ui->inactiveESPList->clear();
- ui->activeESPList->clear();
+ m_inactiveModel->clear();
+ m_activeModel->clear();
setHasData(false);
}
@@ -151,12 +254,12 @@ bool ESPsTab::feedFile(const QString& rootPath, const QString& fullPath)
if (fullPath.endsWith(e, Qt::CaseInsensitive)) {
QString relativePath = fullPath.mid(rootPath.length() + 1);
- auto* item = new ESPItem({rootPath, relativePath});
+ ESPItem esp(rootPath, relativePath);
- if (item->esp().isActive()) {
- ui->activeESPList->addItem(item);
+ if (esp.isActive()) {
+ m_activeModel->add(std::move(esp));
} else {
- ui->inactiveESPList->addItem(item);
+ m_inactiveModel->add(std::move(esp));
}
setHasData(true);
@@ -167,23 +270,31 @@ bool ESPsTab::feedFile(const QString& rootPath, const QString& fullPath)
return false;
}
+void ESPsTab::update()
+{
+ m_inactiveModel->finished();
+ m_activeModel->finished();
+}
+
void ESPsTab::onActivate()
{
- auto* item = selectedInactive();
- if (!item) {
- qWarning("ESPsTab::onActivate(): no selection");
+ const auto index = ui->inactiveESPList->currentIndex();
+ if (!index.isValid()) {
return;
}
- ESP esp = item->esp();
+ auto* esp = m_inactiveModel->getESP(index);
+ if (!esp) {
+ return;
+ }
- if (esp.isActive()) {
+ if (esp->isActive()) {
qWarning("ESPsTab::onActive(): item is already active");
return;
}
- QDir root(esp.rootPath());
- const QFileInfo file(esp.fileInfo());
+ QDir root(esp->rootPath());
+ const QFileInfo file(esp->fileInfo());
QString newName = file.fileName();
@@ -205,10 +316,12 @@ void ESPsTab::onActivate()
}
}
- if (esp.activate(newName)) {
- ui->inactiveESPList->takeItem(ui->inactiveESPList->row(item));
- ui->activeESPList->addItem(item);
- item->setESP(esp);
+ if (esp->activate(newName)) {
+ // copy esp, original will be destroyed
+ auto copy = *esp;
+ m_inactiveModel->removeRow(index.row());
+ m_activeModel->addOne(std::move(copy));
+ selectRow(ui->inactiveESPList, index.row());
} else {
reportError(QObject::tr("Failed to move file"));
}
@@ -216,26 +329,28 @@ void ESPsTab::onActivate()
void ESPsTab::onDeactivate()
{
- auto* item = selectedActive();
- if (!item) {
- qWarning("ESPsTab::onDeactivate(): no selection");
+ const auto index = ui->activeESPList->currentIndex();
+ if (!index.isValid()) {
return;
}
- ESP esp = item->esp();
+ auto* esp = m_activeModel->getESP(index);
+ if (!esp) {
+ return;
+ }
- if (!esp.isActive()) {
+ if (!esp->isActive()) {
qWarning("ESPsTab::onDeactivate(): item is already inactive");
return;
}
- QDir root(esp.rootPath());
+ QDir root(esp->rootPath());
// if we moved the file from optional to active in this session, we move the
// file back to where it came from. Otherwise, it is moved to the new folder
// "optional"
- QString newName = esp.inactivePath();
+ QString newName = esp->inactivePath();
if (newName.isEmpty()) {
if (!root.exists("optional")) {
@@ -245,46 +360,32 @@ void ESPsTab::onDeactivate()
}
}
- newName = QString("optional") + QDir::separator() + esp.fileInfo().fileName();
+ newName = QString("optional") + QDir::separator() + esp->fileInfo().fileName();
}
- if (esp.deactivate(newName)) {
- ui->activeESPList->takeItem(ui->activeESPList->row(item));
- ui->inactiveESPList->addItem(item);
- item->setESP(esp);
+ if (esp->deactivate(newName)) {
+ // copy esp, original will be destroyed
+ auto copy = *esp;
+
+ m_activeModel->removeRow(index.row());
+ m_inactiveModel->addOne(std::move(copy));
+ selectRow(ui->activeESPList, index.row());
} else {
reportError(QObject::tr("Failed to move file"));
}
}
-ESPItem* ESPsTab::selectedInactive()
-{
- auto* item = ui->inactiveESPList->currentItem();
- if (!item) {
- return nullptr;
- }
-
- auto* esp = dynamic_cast<ESPItem*>(item);
- if (!esp) {
- qCritical("ESPsTab: inactive item is not an ESPItem");
- return nullptr;
- }
-
- return esp;
-}
-
-ESPItem* ESPsTab::selectedActive()
+void ESPsTab::selectRow(QListView* list, int row)
{
- auto* item = ui->activeESPList->currentItem();
- if (!item) {
- return nullptr;
+ const auto* model = list->model();
+ const auto count = model->rowCount();
+ if (count == 0) {
+ return;
}
- auto* esp = dynamic_cast<ESPItem*>(item);
- if (!esp) {
- qCritical("ESPsTab: active item is not an ESPItem");
- return nullptr;
+ if (row >= count) {
+ list->setCurrentIndex(model->index(count - 1, 0));
+ } else {
+ list->setCurrentIndex(model->index(row, 0));
}
-
- return esp;
}
diff --git a/src/modinfodialogesps.h b/src/modinfodialogesps.h
index e82ed368..c972074a 100644
--- a/src/modinfodialogesps.h
+++ b/src/modinfodialogesps.h
@@ -4,6 +4,7 @@
#include "modinfodialogtab.h"
class ESPItem;
+class ESPListModel;
class ESPsTab : public ModInfoDialogTab
{
@@ -16,13 +17,15 @@ public:
void clear() override;
bool feedFile(const QString& rootPath, const QString& fullPath) override;
+ void update();
private:
+ ESPListModel* m_inactiveModel;
+ ESPListModel* m_activeModel;
+
void onActivate();
void onDeactivate();
-
- ESPItem* selectedInactive();
- ESPItem* selectedActive();
+ void selectRow(QListView* list, int row);
};
#endif // MODINFODIALOGESPS_H
diff --git a/src/modinfodialogtextfiles.cpp b/src/modinfodialogtextfiles.cpp
index 08b8c988..25d799b1 100644
--- a/src/modinfodialogtextfiles.cpp
+++ b/src/modinfodialogtextfiles.cpp
@@ -9,6 +9,7 @@ public:
void clear()
{
m_files.clear();
+ endResetModel();
}
QModelIndex index(int row, int col, const QModelIndex& ={}) const override
@@ -62,7 +63,7 @@ public:
return (naturalCompare(a.text, b.text) < 0);
});
- emit dataChanged(index(0, 0), index(0, rowCount()));
+ endResetModel();
}
QString fullPath(const QModelIndex& index) const