From 1d4b5a2425c8a627b6489db5af7c2b63798542e8 Mon Sep 17 00:00:00 2001 From: graffy76 Date: Sun, 3 Nov 2013 14:02:41 -0600 Subject: [PATCH] Fix broken launcher content file display / selection scheme Disable selection of content files with missing dependencies (grayed out) --- apps/launcher/datafilespage.cpp | 11 +- apps/launcher/utils/profilescombobox.hpp | 7 ++ .../contentselector/model/contentmodel.cpp | 104 +++++++++++------- .../contentselector/model/contentmodel.hpp | 5 +- .../contentselector/view/contentselector.cpp | 20 +++- 5 files changed, 93 insertions(+), 54 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 71d072599..5ae850566 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -79,8 +79,7 @@ void Launcher::DataFilesPage::loadSettings() //throw addons error here. } */ - if (foundFiles.size() > 0) - mSelector->setCheckStates (foundFiles); + mSelector->setCheckStates (foundFiles); } void Launcher::DataFilesPage::saveSettings(const QString &profile) @@ -177,7 +176,7 @@ void Launcher::DataFilesPage::setProfile (const QString &previous, const QString if (!previous.isEmpty() && savePrevious) saveSettings (previous); - ui.profilesComboBox->setCurrentIndex (ui.profilesComboBox->findText (current)); + ui.profilesComboBox->setCurrentProfile (ui.profilesComboBox->findText (current)); loadSettings(); @@ -232,7 +231,7 @@ void Launcher::DataFilesPage::setupDataFiles() foreach (const QString &item, profiles) addProfile (item, false); - addProfile (profile, true); + setProfile (ui.profilesComboBox->findText(profile), false); loadSettings(); } @@ -289,6 +288,10 @@ void Launcher::DataFilesPage::on_deleteProfileAction_triggered() // Remove the profile from the combobox ui.profilesComboBox->removeItem (ui.profilesComboBox->findText (profile)); + removeProfile(profile); + + saveSettings(); + loadSettings(); checkForDefaultProfile(); diff --git a/apps/launcher/utils/profilescombobox.hpp b/apps/launcher/utils/profilescombobox.hpp index 1e27f66a9..7b83c41b2 100644 --- a/apps/launcher/utils/profilescombobox.hpp +++ b/apps/launcher/utils/profilescombobox.hpp @@ -4,6 +4,8 @@ #include "components/contentselector/view/combobox.hpp" #include "lineedit.hpp" +#include + class QString; class ProfilesComboBox : public ContentSelectorView::ComboBox @@ -21,6 +23,11 @@ public: explicit ProfilesComboBox(QWidget *parent = 0); void setEditEnabled(bool editable); + void setCurrentProfile(int index) + { + ComboBox::setCurrentIndex(index); + mOldProfile = currentText(); + } signals: void signalProfileTextChanged(const QString &item); diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index 0fb1b4216..5f3575eb4 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -13,7 +13,6 @@ ContentSelectorModel::ContentModel::ContentModel(QObject *parent) : mMimeTypes (QStringList() << mMimeType), mColumnCount (1), mDragDropFlags (Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled), - mDefaultFlags (Qt::ItemIsDropEnabled | Qt::ItemIsSelectable), mDropActions (Qt::CopyAction | Qt::MoveAction) { setEncoding ("win1252"); @@ -102,10 +101,53 @@ Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex &index if (!file) return Qt::NoItemFlags; - if (canBeChecked(file)) - return Qt::ItemIsEnabled | mDragDropFlags | mDefaultFlags; + //game files can always be checked + if (file->isGameFile()) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + + Qt::ItemFlags returnFlags; + bool allDependenciesFound = true; + bool gamefileChecked = false; + + //addon can be checked if its gamefile is and all other dependencies exist + foreach (const QString &fileName, file->gameFiles()) + { + bool depFound = false; + foreach (EsmFile *dependency, mFiles) + { + //compare filenames only. Multiple instances + //of the filename (with different paths) is not relevant here. + depFound = (dependency->fileName() == fileName); + + if (!depFound) + continue; + + if (!gamefileChecked) + { + if (isChecked (dependency->filePath())) + gamefileChecked = (dependency->isGameFile()); + } - return Qt::NoItemFlags; + // force it to iterate all files in cases where the current + // dependency is a game file to ensure that a later duplicate + // game file is / is not checked. + // (i.e., break only if it's not a gamefile or the game file has been checked previously) + if (gamefileChecked || !(dependency->isGameFile())) + break; + } + + allDependenciesFound = allDependenciesFound && depFound; + } + + if (gamefileChecked) + { + if (allDependenciesFound) + returnFlags = returnFlags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | mDragDropFlags; + else + returnFlags = Qt::ItemIsSelectable; + } + + return returnFlags; } QVariant ContentSelectorModel::ContentModel::data(const QModelIndex &index, int role) const @@ -173,7 +215,7 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex &index, int if (file->isGameFile()) return ContentType_GameFile; else - if (flags(index) & mDefaultFlags) + if (flags(index)) return ContentType_Addon; break; @@ -215,19 +257,13 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex &index, const case Qt::UserRole+1: { - setCheckState(fileName, value.toBool()); - - emit dataChanged(index, index); + success = (flags (index) & Qt::ItemIsEnabled); - foreach (EsmFile *file, mFiles) + if (success) { - if (file->gameFiles().contains(fileName)) - { - QModelIndex idx = indexFromItem(file); - emit dataChanged(idx, idx); - } + success = setCheckState(fileName, value.toBool()); + emit dataChanged(index, index); } - success = true; } break; @@ -377,32 +413,6 @@ bool ContentSelectorModel::ContentModel::dropMimeData(const QMimeData *data, Qt: return true; } -bool ContentSelectorModel::ContentModel::canBeChecked(const EsmFile *file) const -{ - //game files can always be checked - if (file->isGameFile()) - return true; - - //addon can be checked if its gamefile is - foreach (const QString &fileName, file->gameFiles()) - { - foreach (EsmFile *dependency, mFiles) - { - //compare filenames only. Multiple instances - //of the filename (with different paths) is not relevant here. - if (!(dependency->fileName() == fileName)) - continue; - - if (dependency->isGameFile()) - { - if (isChecked(dependency->filePath())) - return true; - } - } - } - return false; -} - void ContentSelectorModel::ContentModel::addFile(EsmFile *file) { beginInsertRows(QModelIndex(), mFiles.count(), mFiles.count()); @@ -510,6 +520,11 @@ bool ContentSelectorModel::ContentModel::isChecked(const QString& name) const return false; } +bool ContentSelectorModel::ContentModel::isEnabled (QModelIndex index) const +{ + return (flags(index) & Qt::ItemIsEnabled); +} + void ContentSelectorModel::ContentModel::setCheckStates (const QStringList &fileList, bool isChecked) { foreach (const QString &file, fileList) @@ -518,6 +533,11 @@ void ContentSelectorModel::ContentModel::setCheckStates (const QStringList &file } } +void ContentSelectorModel::ContentModel::refreshModel() +{ + emit dataChanged (index(0,0), index(rowCount()-1,0)); +} + bool ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool checkState) { if (name.isEmpty()) @@ -537,7 +557,7 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool emit dataChanged(indexFromItem(item(name)), indexFromItem(item(name))); if (file->isGameFile()) - emit dataChanged (index(0,0), index(rowCount()-1,0)); + refreshModel(); //if we're checking an item, ensure all "upstream" files (dependencies) are checked as well. if (state == Qt::Checked) diff --git a/components/contentselector/model/contentmodel.hpp b/components/contentselector/model/contentmodel.hpp index ae49dd27d..8c8c2124b 100644 --- a/components/contentselector/model/contentmodel.hpp +++ b/components/contentselector/model/contentmodel.hpp @@ -44,19 +44,21 @@ namespace ContentSelectorModel QModelIndex indexFromItem(const EsmFile *item) const; const EsmFile *item(const QString &name) const; + bool isEnabled (QModelIndex index) const; bool isChecked(const QString &name) const; bool setCheckState(const QString &name, bool isChecked); void setCheckStates (const QStringList &fileList, bool isChecked); ContentFileList checkedItems() const; void uncheckAll(); + void refreshModel(); + private: void addFile(EsmFile *file); const EsmFile *item(int row) const; EsmFile *item(int row); - bool canBeChecked(const EsmFile *file) const; void sortFiles(); ContentFileList mFiles; @@ -69,7 +71,6 @@ namespace ContentSelectorModel QStringList mMimeTypes; int mColumnCount; Qt::ItemFlags mDragDropFlags; - Qt::ItemFlags mDefaultFlags; Qt::DropActions mDropActions; }; } diff --git a/components/contentselector/view/contentselector.cpp b/components/contentselector/view/contentselector.cpp index 4758dd5a0..b962fa9ce 100644 --- a/components/contentselector/view/contentselector.cpp +++ b/components/contentselector/view/contentselector.cpp @@ -12,6 +12,8 @@ #include #include +#include + ContentSelectorView::ContentSelector::ContentSelector(QWidget *parent) : QObject(parent) { @@ -89,9 +91,12 @@ void ContentSelectorView::ContentSelector::clearCheckStates() void ContentSelectorView::ContentSelector::setCheckStates(const QStringList &list) { if (list.isEmpty()) - return; - - mContentModel->setCheckStates (list, true); + { + qDebug() << "refreshing model"; + slotCurrentGameFileIndexChanged (ui.gameFileView->currentIndex()); + } + else + mContentModel->setCheckStates (list, true); } ContentSelectorModel::ContentFileList @@ -152,14 +157,17 @@ void ContentSelectorView::ContentSelector::slotCurrentGameFileIndexChanged(int i void ContentSelectorView::ContentSelector::slotAddonTableItemClicked(const QModelIndex &index) { - QAbstractItemModel *const model = ui.addonView->model(); + QModelIndex sourceIndex = mAddonProxyModel->mapToSource (index); + + if (!mContentModel->isEnabled (sourceIndex)) + return; Qt::CheckState checkState = Qt::Unchecked; - if (model->data(index, Qt::CheckStateRole).toInt() == Qt::Unchecked) + if (mContentModel->data(sourceIndex, Qt::CheckStateRole).toInt() == Qt::Unchecked) checkState = Qt::Checked; - model->setData(index, checkState, Qt::CheckStateRole); + mContentModel->setData(sourceIndex, checkState, Qt::CheckStateRole); if (checkState == Qt::Checked) emit signalAddonFileSelected (index.row());