diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 92cabffff..49dedd829 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -11,7 +11,6 @@ set(LAUNCHER settings/launchersettings.cpp utils/checkablemessagebox.cpp - utils/textinputdialog.cpp ${CMAKE_SOURCE_DIR}/files/launcher/launcher.rc ) @@ -32,8 +31,6 @@ set(LAUNCHER_HEADER settings/settingsbase.hpp utils/checkablemessagebox.hpp - utils/textinputdialog.hpp - ) if(NOT WIN32) LIST(APPEND LAUNCHER_HEADER unshieldthread.hpp) @@ -49,7 +46,6 @@ set(LAUNCHER_HEADER_MOC textslotmsgbox.hpp utils/checkablemessagebox.hpp - utils/textinputdialog.hpp ) if(NOT WIN32) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index eee530672..a705ae37d 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -17,177 +17,182 @@ #include "settings/gamesettings.hpp" #include "settings/launchersettings.hpp" -#include "utils/textinputdialog.hpp" #include "components/contentselector/view/contentselector.hpp" -#include - DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent) : mCfgMgr(cfg) , mGameSettings(gameSettings) , mLauncherSettings(launcherSettings) + , QWidget(parent) { - unsigned char flags; + setObjectName ("DataFilesPage"); + + unsigned char flags; - flags = ContentSelectorView::Flag_Content | ContentSelectorView::Flag_Profile; + flags = ContentSelectorView::Flag_Content | ContentSelectorView::Flag_Profile; - ContentSelectorView::ContentSelector::configure(this, flags); + ContentSelectorView::ContentSelector::configure(this, flags); + mSelector = &ContentSelectorView::ContentSelector::instance(); setupDataFiles(); - ContentSelectorView::ContentSelector &cSelector = - ContentSelectorView::ContentSelector::instance(); - connect (&cSelector, SIGNAL (signalProfileRenamed (QString, QString)), + connect (mSelector, SIGNAL (signalProfileRenamed (QString, QString)), this, SLOT (slotProfileRenamed (QString, QString))); - connect (&cSelector, SIGNAL (signalProfileChanged (QString, QString)), - this, SLOT (slotProfileChanged (QString, QString))); + connect (mSelector, SIGNAL (signalProfileChangedByUser (QString, QString)), + this, SLOT (slotProfileChangedByUser (QString, QString))); - connect (&cSelector, SIGNAL (signalProfileDeleted (QString)), + connect (mSelector, SIGNAL (signalProfileDeleted (QString)), this, SLOT (slotProfileDeleted (QString))); - connect (&cSelector, SIGNAL (signalProfileAdded ()), - this, SLOT (slotProfileAdded ())); + connect (mSelector, SIGNAL (signalAddNewProfile (QString)), + this, SLOT (slotAddNewProfile (QString))); } void DataFilesPage::loadSettings() { + QString profileName = mSelector->getProfileText(); - QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); - - if (profile.isEmpty()) - return; + QStringList files = mLauncherSettings.values(QString("Profiles/") + profileName + QString("/game"), Qt::MatchExactly); + QStringList addons = mLauncherSettings.values(QString("Profiles/") + profileName + QString("/addon"), Qt::MatchExactly); - QStringList files = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly); - QStringList addons = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly); + mSelector->clearCheckStates(); - foreach (const QString &file, addons) - files.append(file); + if (files.size() > 0) + mSelector->setGameFile(files.at(0)); + else + mSelector->setGameFile(); - ContentSelectorView::ContentSelector::instance().setCheckStates(files); + mSelector->setCheckStates(addons); } -void DataFilesPage::saveSettings() +void DataFilesPage::saveSettings(const QString &profile) { - ContentSelectorModel::ContentFileList items = - ContentSelectorView::ContentSelector::instance().selectedFiles(); + QString profileName = profile; - if (items.size() == 0) - return; + if (profileName.isEmpty()) + profileName = mSelector->getProfileText(); - QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); + //retrieve the files selected for the profile + ContentSelectorModel::ContentFileList items = mSelector->selectedFiles(); - if (profile.isEmpty()) { - profile = ContentSelectorView::ContentSelector::instance().getProfileText(); - mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile); - } + removeProfile (profileName); - mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); - mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); + mGameSettings.remove(QString("game")); + mGameSettings.remove(QString("addon")); - mGameSettings.remove(QString("master")); - mGameSettings.remove(QString("plugin")); + //set the value of the current profile (not necessarily the profile being saved!) + mLauncherSettings.setValue(QString("Profiles/currentprofile"), mSelector->getProfileText()); foreach(const ContentSelectorModel::EsmFile *item, items) { if (item->gameFiles().size() == 0) { - mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item->fileName()); - mGameSettings.setMultiValue(QString("master"), item->fileName()); - + mLauncherSettings.setMultiValue(QString("Profiles/") + profileName + QString("/game"), item->fileName()); + mGameSettings.setMultiValue(QString("game"), item->fileName()); } else { - mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item->fileName()); - mGameSettings.setMultiValue(QString("plugin"), item->fileName()); + mLauncherSettings.setMultiValue(QString("Profiles/") + profileName + QString("/addon"), item->fileName()); + mGameSettings.setMultiValue(QString("addon"), item->fileName()); } } } -void DataFilesPage::slotProfileDeleted (const QString &item) +void DataFilesPage::removeProfile(const QString &profile) { - mLauncherSettings.remove(QString("Profiles/") + item + QString("/master")); - mLauncherSettings.remove(QString("Profiles/") + item + QString("/plugin")); + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/game")); + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/addon")); } -void DataFilesPage::slotProfileChanged(const QString &previous, const QString ¤t) +void DataFilesPage::changeProfiles(const QString &previous, const QString ¤t, bool savePrevious) { - if (previous.isEmpty()) + //abort if no change (typically a duplicate signal) + if (previous == current) return; - if (ContentSelectorView::ContentSelector::instance().getProfileIndex (previous) == -1) - return; // Profile was deleted + int index = -1; - // Store the previous profile - mLauncherSettings.setValue(QString("Profiles/currentprofile"), previous); - saveSettings(); - mLauncherSettings.setValue(QString("Profiles/currentprofile"), current); + if (!previous.isEmpty()) + index = mSelector->getProfileIndex(previous); + + // Store the previous profile if it exists + if ( (index != -1) && savePrevious) + saveSettings(previous); loadSettings(); } -void DataFilesPage::slotProfileRenamed(const QString &previous, const QString ¤t) +void DataFilesPage::slotAddNewProfile(const QString &profile) { - if (previous.isEmpty()) - return; - - // Save the new profile name - mLauncherSettings.setValue(QString("Profiles/currentprofile"), current); + saveSettings(); + mSelector->clearCheckStates(); + mSelector->addProfile(profile, true); + mSelector->setGameFile(); saveSettings(); - // Remove the old one - mLauncherSettings.remove(QString("Profiles/") + previous + QString("/master")); - mLauncherSettings.remove(QString("Profiles/") + previous + QString("/plugin")); + emit signalProfileChanged(mSelector->getProfileIndex(profile)); +} - // Remove the profile from the combobox - ContentSelectorView::ContentSelector::instance().removeProfile (previous); +void DataFilesPage::slotProfileDeleted (const QString &item) +{ + removeProfile (item); +} - loadSettings(); +void DataFilesPage::slotProfileChangedByUser(const QString &previous, const QString ¤t) +{ + changeProfiles(previous, current); + emit signalProfileChanged(mSelector->getProfileIndex(current)); } -void DataFilesPage::slotProfileAdded() +void DataFilesPage::slotProfileRenamed(const QString &previous, const QString ¤t) { - TextInputDialog newDialog (tr("New Profile"), tr("Profile name:"), this); + if (previous.isEmpty()) + return; - // connect(mNewDialog->lineEdit(), SIGNAL(textChanged(QString)), - // this, SLOT(updateOkButton(QString))); + // Save the new profile name + saveSettings(); - if (newDialog.exec() == QDialog::Accepted) - { - QString profile = newDialog.lineEdit()->text(); + // Remove the old one + removeProfile (previous); - ContentSelectorView::ContentSelector - ::instance().addProfile(profile, true); - } + loadSettings(); } -void DataFilesPage::setProfilesComboBoxIndex(int index) +void DataFilesPage::slotProfileChanged(int index) { - ContentSelectorView::ContentSelector::instance().setProfileIndex(index); + mSelector->setProfile(index); } void DataFilesPage::setupDataFiles() { - ContentSelectorView::ContentSelector &cSelector = - ContentSelectorView::ContentSelector::instance(); - QStringList paths = mGameSettings.getDataDirs(); foreach (const QString &path, paths) - cSelector.addFiles(path); + mSelector->addFiles(path); QString dataLocal = mGameSettings.getDataLocal(); if (!dataLocal.isEmpty()) - cSelector.addFiles(dataLocal); + mSelector->addFiles(dataLocal); QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); foreach (const QString &item, profiles) - cSelector.addProfile (item); + mSelector->addProfile (item); - cSelector.addProfile (profile, true); + mSelector->addProfile (profile, true); loadSettings(); } + +QAbstractItemModel *DataFilesPage::profilesModel() const +{ + return mSelector->profilesModel(); +} + +int DataFilesPage::profilesIndex() const +{ + return mSelector->getProfileIndex(mSelector->getProfileText()); +} diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 6ed5d9ce9..47e28493d 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -15,22 +15,26 @@ class LauncherSettings; namespace Files { struct ConfigurationManager; } +namespace ContentSelectorView { class ContentSelector; } class DataFilesPage : public QWidget { Q_OBJECT + ContentSelectorView::ContentSelector *mSelector; + public: DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0); - QAbstractItemModel* profilesComboBoxModel(); - int profilesComboBoxIndex(); + QAbstractItemModel* profilesModel() const; + int profilesIndex() const; void writeConfig(QString profile = QString()); - void saveSettings(); + void saveSettings(const QString &profile = ""); + void loadSettings(); signals: - void profileChanged(int index); + void signalProfileChanged(int index); public slots: //void showContextMenu(const QPoint &point); @@ -38,11 +42,11 @@ public slots: private slots: - void slotProfileAdded(); - void slotProfileChanged(const QString &previous, const QString ¤t); + void slotAddNewProfile(const QString &profile); + void slotProfileChangedByUser(const QString &previous, const QString ¤t); + void slotProfileChanged(int); void slotProfileRenamed(const QString &previous, const QString ¤t); void slotProfileDeleted(const QString &item); - void setProfilesComboBoxIndex(int index); private: @@ -58,8 +62,8 @@ private: void setupDataFiles(); void setupConfig(); void readConfig(); - - void loadSettings(); + void removeProfile (const QString &profile); + void changeProfiles(const QString &previous, const QString ¤t, bool savePrevious = true); }; #endif diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 4d9ce14d6..2c6c711ea 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -38,6 +38,7 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &g , mGraphicsSettings(graphicsSetting) , QWidget(parent) { + setObjectName ("GraphicsPage"); setupUi(this); // Set the maximum res we can set in windowed mode diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 311e3a25c..fe9ca141e 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -106,10 +106,10 @@ void MainDialog::createPages() mPlayPage = new PlayPage(this); mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this); mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); -/// reimplement datafilespage functions to provide access + // Set the combobox of the play page to imitate the combobox on the datafilespage - // mPlayPage->setProfilesComboBoxModel(mDataFilesPage->profilesComboBoxModel()); - // mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->profilesComboBoxIndex()); + mPlayPage->setProfilesModel(mDataFilesPage->profilesModel()); + mPlayPage->setProfilesIndex(mDataFilesPage->profilesIndex()); // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); @@ -121,8 +121,8 @@ void MainDialog::createPages() connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play())); - connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage, SLOT(setProfilesComboBoxIndex(int))); - connect(mDataFilesPage, SIGNAL(profileChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); + connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int))); + connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int))); } @@ -316,7 +316,25 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) if (!current) current = previous; - pagesWidget->setCurrentIndex(iconWidget->row(current)); + int currentIndex = iconWidget->row(current); + int previousIndex = iconWidget->row(previous); + + pagesWidget->setCurrentIndex(currentIndex); + + DataFilesPage *previousPage = dynamic_cast(pagesWidget->widget(previousIndex)); + DataFilesPage *currentPage = dynamic_cast(pagesWidget->widget(currentIndex)); + + //special call to update/save data files page list view when it's displayed/hidden. + if (previousPage) + { + if (previousPage->objectName() == "DataFilesPage") + previousPage->saveSettings(); + } + else if (currentPage) + { + if (currentPage->objectName() == "DataFilesPage") + currentPage->loadSettings(); + } } bool MainDialog::setupLauncherSettings() diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp index 46900c595..fc1ed1c69 100644 --- a/apps/launcher/playpage.cpp +++ b/apps/launcher/playpage.cpp @@ -8,6 +8,7 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent) { + setObjectName ("PlayPage"); setupUi(this); // Hacks to get the stylesheet look properly @@ -17,26 +18,21 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent) #endif profilesComboBox->setView(new QListView()); - connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int))); + connect(profilesComboBox, SIGNAL(activated(int)), this, SIGNAL (signalProfileChanged(int))); connect(playButton, SIGNAL(clicked()), this, SLOT(slotPlayClicked())); } -void PlayPage::setProfilesComboBoxModel(QAbstractItemModel *model) +void PlayPage::setProfilesModel(QAbstractItemModel *model) { profilesComboBox->setModel(model); } -void PlayPage::setProfilesComboBoxIndex(int index) +void PlayPage::setProfilesIndex(int index) { profilesComboBox->setCurrentIndex(index); } -void PlayPage::slotCurrentIndexChanged(int index) -{ - emit profileChanged(index); -} - void PlayPage::slotPlayClicked() { emit playButtonClicked(); diff --git a/apps/launcher/playpage.hpp b/apps/launcher/playpage.hpp index 4306396bd..42edfadb1 100644 --- a/apps/launcher/playpage.hpp +++ b/apps/launcher/playpage.hpp @@ -15,17 +15,16 @@ class PlayPage : public QWidget, private Ui::PlayPage public: PlayPage(QWidget *parent = 0); - void setProfilesComboBoxModel(QAbstractItemModel *model); + void setProfilesModel(QAbstractItemModel *model); signals: - void profileChanged(int index); + void signalProfileChanged(int index); void playButtonClicked(); public slots: - void setProfilesComboBoxIndex(int index); + void setProfilesIndex(int index); private slots: - void slotCurrentIndexChanged(int index); void slotPlayClicked(); diff --git a/apps/opencs/view/doc/filedialog.cpp b/apps/opencs/view/doc/filedialog.cpp index b1b72dc1f..efa31100a 100644 --- a/apps/opencs/view/doc/filedialog.cpp +++ b/apps/opencs/view/doc/filedialog.cpp @@ -34,7 +34,7 @@ void CSVDoc::FileDialog::addFiles(const QString &path) QString CSVDoc::FileDialog::filename() { - return ContentSelectorView::ContentSelector::instance().filename(); + return ContentSelectorView::ContentSelector::instance().projectFilename(); } QStringList CSVDoc::FileDialog::selectedFilePaths() diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index ebce4578b..103c6f412 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -85,6 +85,8 @@ if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) view/profilescombobox view/comboboxlineedit view/lineedit view/contentselector view/filewidget view/adjusterwidget + view/textinputdialog + ) include(${QT_USE_FILE}) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index db6431810..a9796a1fb 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -391,7 +391,6 @@ bool ContentSelectorModel::ContentModel::canBeChecked(const EsmFile *file) const return true; } } - return false; } @@ -448,6 +447,39 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path) } delete decoder; + + sortFiles(); +} + +void ContentSelectorModel::ContentModel::sortFiles() +{ + //first, sort the model such that all dependencies are ordered upstream (gamefile) first. + bool movedFiles = true; + int fileCount = mFiles.size(); + + //Dependency sort + //iterate until no sorting of files occurs + while (movedFiles) + { + movedFiles = false; + //iterate each file, obtaining a reference to it's gamefiles list + for (int i = 0; i < fileCount; i++) + { + const QStringList &gamefiles = mFiles.at(i)->gameFiles(); + //iterate each file after the current file, verifying that none of it's + //dependencies appear. + for (int j = i + 1; j < fileCount; j++) + { + if (gamefiles.contains(mFiles.at(j)->fileName())) + { + mFiles.move(j, i); + movedFiles = true; + } + } + if (movedFiles) + break; + } + } } bool ContentSelectorModel::ContentModel::isChecked(const QString& name) const @@ -460,6 +492,7 @@ bool ContentSelectorModel::ContentModel::isChecked(const QString& name) const void ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool checkState) { + if (name.isEmpty()) return; @@ -469,9 +502,14 @@ void ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool state = Qt::Checked; mCheckStates[name] = state; + emit dataChanged(indexFromItem(item(name)), indexFromItem(item(name))); const EsmFile *file = item(name); + if (file->isGameFile()) + emit dataChanged (index(0,0), index(rowCount()-1,0)); + + //if we're checking an item, ensure all "upstream" files (dependencies) are checked as well. if (state == Qt::Checked) { foreach (const QString &upstreamName, file->gameFiles()) @@ -482,24 +520,23 @@ void ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool continue; if (!isChecked(upstreamName)) - { mCheckStates[upstreamName] = Qt::Checked; - emit dataChanged(indexFromItem(upstreamFile), indexFromItem(upstreamFile)); - } + + emit dataChanged(indexFromItem(upstreamFile), indexFromItem(upstreamFile)); } } - else if (state == Qt::Unchecked) + //otherwise, if we're unchecking an item (or the file is a game file) ensure all downstream files are unchecked. + if (state == Qt::Unchecked) { foreach (const EsmFile *downstreamFile, mFiles) { if (downstreamFile->gameFiles().contains(name)) { if (mCheckStates.contains(downstreamFile->fileName())) - { mCheckStates[downstreamFile->fileName()] = Qt::Unchecked; - emit dataChanged(indexFromItem(downstreamFile), indexFromItem(downstreamFile)); - } + + emit dataChanged(indexFromItem(downstreamFile), indexFromItem(downstreamFile)); } } } diff --git a/components/contentselector/model/contentmodel.hpp b/components/contentselector/model/contentmodel.hpp index a2a57f850..feea3643b 100644 --- a/components/contentselector/model/contentmodel.hpp +++ b/components/contentselector/model/contentmodel.hpp @@ -56,19 +56,20 @@ namespace ContentSelectorModel EsmFile *item(int row); bool canBeChecked(const EsmFile *file) const; + void sortFiles(); ContentFileList mFiles; QHash mCheckStates; QTextCodec *mCodec; public: + QString mMimeType; QStringList mMimeTypes; int mColumnCount; Qt::ItemFlags mDragDropFlags; Qt::ItemFlags mDefaultFlags; Qt::DropActions mDropActions; - }; } #endif // CONTENTMODEL_HPP diff --git a/components/contentselector/view/contentselector.cpp b/components/contentselector/view/contentselector.cpp index 54199626e..6965c948e 100644 --- a/components/contentselector/view/contentselector.cpp +++ b/components/contentselector/view/contentselector.cpp @@ -5,7 +5,6 @@ #include -#include #include #include #include @@ -14,6 +13,9 @@ #include "filewidget.hpp" #include "adjusterwidget.hpp" +#include "textinputdialog.hpp" + +#include ContentSelectorView::ContentSelector *ContentSelectorView::ContentSelector::mInstance = 0; QStringList ContentSelectorView::ContentSelector::mFilePaths; @@ -33,7 +35,8 @@ ContentSelectorView::ContentSelector& ContentSelectorView::ContentSelector::inst ContentSelectorView::ContentSelector::ContentSelector(QWidget *parent, unsigned char flags) : QWidget(parent), mFlags (flags), - mAdjusterWidget (0), mFileWidget (0) + mAdjusterWidget (0), mFileWidget (0), + mIgnoreProfileSignal (false) { ui.setupUi (this); @@ -53,14 +56,6 @@ ContentSelectorView::ContentSelector::ContentSelector(QWidget *parent, unsigned */ } -QString ContentSelectorView::ContentSelector::getNewProfileName() -{ - // Create a dialog for the new profile name input - //mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); - - //connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); - return ""; -} bool ContentSelectorView::ContentSelector::isFlagged(SelectorFlags flag) const { @@ -94,6 +89,8 @@ void ContentSelectorView::ContentSelector::buildGameFileView() return; } + ui.gameFileView->setVisible (true); + mGameFileProxyModel = new QSortFilterProxyModel(this); mGameFileProxyModel->setFilterRegExp(QString::number((int)ContentSelectorModel::ContentType_GameFile)); mGameFileProxyModel->setFilterRole (Qt::UserRole); @@ -102,7 +99,7 @@ void ContentSelectorView::ContentSelector::buildGameFileView() ui.gameFileView->setPlaceholderText(QString("Select a game file...")); ui.gameFileView->setModel(mGameFileProxyModel); - connect(ui.gameFileView, SIGNAL(currentIndexChanged(int)), this, SLOT (slotCurrentGameFileIndexChanged(int))); + connect (ui.gameFileView, SIGNAL(currentIndexChanged(int)), this, SLOT (slotCurrentGameFileIndexChanged(int))); ui.gameFileView->setCurrentIndex(-1); } @@ -115,6 +112,8 @@ void ContentSelectorView::ContentSelector::buildAddonView() return; } + ui.addonView->setVisible (true); + mAddonProxyModel = new QSortFilterProxyModel(this); mAddonProxyModel->setFilterRegExp (QString::number((int)ContentSelectorModel::ContentType_Addon)); mAddonProxyModel->setFilterRole (Qt::UserRole); @@ -129,31 +128,48 @@ void ContentSelectorView::ContentSelector::buildAddonView() void ContentSelectorView::ContentSelector::buildProfilesView() { if (!isFlagged (Flag_Profile)) + { + ui.profileGroupBox->setVisible(false); return; + } + + ui.profileGroupBox->setVisible (true); // Add the actions to the toolbuttons ui.newProfileButton->setDefaultAction (ui.newProfileAction); ui.deleteProfileButton->setDefaultAction (ui.deleteProfileAction); + //enable ui elements ui.profilesComboBox->addItem ("Default"); ui.profilesComboBox->setPlaceholderText (QString("Select a profile...")); + if (!ui.profilesComboBox->isEnabled()) + ui.profilesComboBox->setEnabled(true); + + if (!ui.deleteProfileAction->isEnabled()) + ui.deleteProfileAction->setEnabled(true); + + //establish connections connect (ui.profilesComboBox, SIGNAL (currentIndexChanged(int)), this, SLOT(slotCurrentProfileIndexChanged(int))); connect (ui.profilesComboBox, SIGNAL (profileRenamed(QString,QString)), this, SIGNAL(signalProfileRenamed(QString,QString))); - connect (ui.profilesComboBox, SIGNAL (profileChanged(QString,QString)), this, SIGNAL(signalProfileChanged(QString,QString))); + connect (ui.profilesComboBox, SIGNAL (signalProfileChanged(QString,QString)), this, SIGNAL(signalProfileChangedByUser(QString,QString))); connect (ui.profilesComboBox, SIGNAL (signalProfileTextChanged(QString)), this, SLOT (slotProfileTextChanged (QString))); ui.profileGroupBox->setVisible (true); + ui.projectButtonBox->setVisible (false); } void ContentSelectorView::ContentSelector::buildLoadAddonView() { if (!isFlagged (Flag_LoadAddon)) { - ui.projectGroupBox->setVisible (false); + if (!isFlagged (Flag_NewAddon)) + ui.projectGroupBox->setVisible (false); + return; } + ui.projectGroupBox->setVisible (true); ui.projectCreateButton->setVisible (false); ui.projectGroupBox->setTitle (""); @@ -165,10 +181,14 @@ void ContentSelectorView::ContentSelector::buildNewAddonView() { if (!isFlagged (Flag_NewAddon)) { - ui.profileGroupBox->setVisible (false); + if (!isFlagged (Flag_LoadAddon)) + ui.projectGroupBox->setVisible (false); + return; } + ui.projectGroupBox->setVisible (true); + mFileWidget = new CSVDoc::FileWidget (this); mAdjusterWidget = new CSVDoc::AdjusterWidget (this); @@ -190,18 +210,36 @@ void ContentSelectorView::ContentSelector::buildNewAddonView() connect(ui.projectButtonBox, SIGNAL(rejected()), this, SIGNAL(rejected())); } +void ContentSelectorView::ContentSelector::setGameFile(const QString &filename) +{ + int index = -1; + + if (!filename.isEmpty()) + { + index = ui.gameFileView->findText(filename); + + //verify that the current index is also checked in the model + mContentModel->setCheckState(filename, true); + } + + ui.gameFileView->setCurrentIndex(index); +} + +void ContentSelectorView::ContentSelector::clearCheckStates() +{ + mContentModel->uncheckAll(); +} + void ContentSelectorView::ContentSelector::setCheckStates(const QStringList &list) { if (list.isEmpty()) return; - mContentModel->uncheckAll(); - foreach (const QString &file, list) mContentModel->setCheckState(file, Qt::Checked); } -QString ContentSelectorView::ContentSelector::filename() const +QString ContentSelectorView::ContentSelector::projectFilename() const { QString filepath = ""; @@ -211,26 +249,13 @@ QString ContentSelectorView::ContentSelector::filename() const return filepath; } -QStringList ContentSelectorView::ContentSelector::selectedFilePaths() const -{ - QStringList filePaths; - - if (mContentModel) - { - foreach (ContentSelectorModel::EsmFile *file, mContentModel->checkedItems()) - filePaths.append(file->path()); - } - - return filePaths; -} - ContentSelectorModel::ContentFileList ContentSelectorView::ContentSelector::selectedFiles() const { - if (mContentModel) - return mContentModel->checkedItems(); + if (!mContentModel) + return ContentSelectorModel::ContentFileList(); - return ContentSelectorModel::ContentFileList(); + return mContentModel->checkedItems(); } @@ -243,78 +268,58 @@ void ContentSelectorView::ContentSelector::addFiles(const QString &path) { mInstance->mContentModel->addFiles(path); mInstance->ui.gameFileView->setCurrentIndex(-1); - mInstance->mContentModel->uncheckAll(); } } -void ContentSelectorView::ContentSelector::removeProfile(const QString &item) -{ - int idx = ui.profilesComboBox->findText(item); - - if (idx != -1) - ui.profilesComboBox->removeItem(idx); -} - int ContentSelectorView::ContentSelector::getProfileIndex ( const QString &item) const { return ui.profilesComboBox->findText (item); } -void ContentSelectorView::ContentSelector::setProfileIndex(int index) -{ - if (index >=0 && index < ui.profilesComboBox->count()) - ui.profilesComboBox->setCurrentIndex(index); -} - void ContentSelectorView::ContentSelector::addProfile (const QString &item, bool setAsCurrent) { if (item.isEmpty()) return; + QString previous = ui.profilesComboBox->currentText(); + if (ui.profilesComboBox->findText(item) == -1) ui.profilesComboBox->addItem(item); if (setAsCurrent) - ui.profilesComboBox->setCurrentIndex(ui.profilesComboBox->findText(item)); - - enableProfilesComboBox(); + setProfile (ui.profilesComboBox->findText(item)); } -QString ContentSelectorView::ContentSelector::getProfileText() const +void ContentSelectorView::ContentSelector::setProfile(int index) { - return ui.profilesComboBox->currentText(); + //programmatic change requires second call to non-signalized "slot" since no signal responses + //occur for programmatic changes to the profilesComboBox. + if (index >= -1 && index < ui.profilesComboBox->count()) + { + QString previous = ui.profilesComboBox->itemText(ui.profilesComboBox->currentIndex()); + QString current = ui.profilesComboBox->itemText(index); + + ui.profilesComboBox->setCurrentIndex(index); + } } -void ContentSelectorView::ContentSelector::enableProfilesComboBox() +QString ContentSelectorView::ContentSelector::getProfileText() const { - if (!ui.profilesComboBox->isEnabled()) - ui.profilesComboBox->setEnabled(true); - - if (!ui.deleteProfileAction->isEnabled()) - ui.deleteProfileAction->setEnabled(true); - - ui.projectButtonBox->button(QDialogButtonBox::Open)->setEnabled (true); + return ui.profilesComboBox->currentText(); } -QStringList ContentSelectorView::ContentSelector::checkedItemsPaths() +QAbstractItemModel *ContentSelectorView::ContentSelector::profilesModel() const { - QStringList itemPaths; - - foreach( const ContentSelectorModel::EsmFile *file, mContentModel->checkedItems()) - itemPaths << file->path(); - - return itemPaths; + return ui.profilesComboBox->model(); } void ContentSelectorView::ContentSelector::slotCurrentProfileIndexChanged(int index) { //don't allow deleting "Default" profile - bool success = (ui.profilesComboBox->itemText(index) == "Default"); + bool success = (ui.profilesComboBox->itemText(index) != "Default"); ui.deleteProfileAction->setEnabled(success); ui.profilesComboBox->setEditEnabled(success); - - emit signalProfileChanged(index); } void ContentSelectorView::ContentSelector::slotCurrentGameFileIndexChanged(int index) @@ -370,10 +375,12 @@ void ContentSelectorView::ContentSelector::slotUpdateCreateButton(bool) ui.projectCreateButton->setEnabled(validGameFile && validFilename); } - void ContentSelectorView::ContentSelector::on_newProfileAction_triggered() { - emit signalProfileAdded(); + TextInputDialog newDialog (tr("New Profile"), tr("Profile name:"), this); + + if (newDialog.exec() == QDialog::Accepted) + emit signalAddNewProfile(newDialog.getText()); } void ContentSelectorView::ContentSelector::on_deleteProfileAction_triggered() @@ -402,11 +409,6 @@ void ContentSelectorView::ContentSelector::on_deleteProfileAction_triggered() //signal for removal from model emit signalProfileDeleted (profile); -} -/* -void ContentSelectorView::ContentSelector::slotUpdateOkButton(const QString &text) -{ - bool success = (ui.profilesComboBox->findText(text) == -1); - mNewDialog->setOkButtonEnabled(success); -}*/ + slotCurrentProfileIndexChanged(ui.profilesComboBox->currentIndex()); +} diff --git a/components/contentselector/view/contentselector.hpp b/components/contentselector/view/contentselector.hpp index caf9cc670..64b9b3732 100644 --- a/components/contentselector/view/contentselector.hpp +++ b/components/contentselector/view/contentselector.hpp @@ -7,7 +7,6 @@ #include "../model/contentmodel.hpp" class QSortFilterProxyModel; -class TextInputDialog; namespace CSVDoc { @@ -29,6 +28,7 @@ namespace ContentSelectorView Q_OBJECT unsigned char mFlags; + bool mIgnoreProfileSignal; static ContentSelector *mInstance; static QStringList mFilePaths; @@ -36,8 +36,6 @@ namespace ContentSelectorView CSVDoc::FileWidget *mFileWidget; CSVDoc::AdjusterWidget *mAdjusterWidget; - TextInputDialog *mNewDialog; - protected: ContentSelectorModel::ContentModel *mContentModel; @@ -45,26 +43,28 @@ namespace ContentSelectorView QSortFilterProxyModel *mAddonProxyModel; public: + explicit ContentSelector(QWidget *parent = 0, unsigned char flags = Flag_Content); static void configure(QWidget *subject, unsigned char flags = Flag_Content); static ContentSelector &instance(); static void addFiles(const QString &path); + void clearCheckStates(); void setCheckStates (const QStringList &list); - QStringList checkedItemsPaths(); ContentSelectorModel::ContentFileList *CheckedItems(); - QString filename() const; + QString projectFilename() const; ContentSelectorModel::ContentFileList selectedFiles() const; - QStringList selectedFilePaths() const; + QAbstractItemModel *profilesModel() const; + void setGameFile (const QString &filename = ""); void addProfile (const QString &item, bool setAsCurrent = false); - void removeProfile (const QString &item); + void setProfile (int index); int getProfileIndex (const QString &item) const; - void setProfileIndex (int index); QString getProfileText() const; + private: Ui::DataFilesPage ui; @@ -77,22 +77,18 @@ namespace ContentSelectorView void buildLoadAddonView(); bool isFlagged(SelectorFlags flag) const; - QString getNewProfileName(); - void enableProfilesComboBox(); signals: + void accepted(); void rejected(); - void signalProfileChanged(int index); - void signalGameFileChanged(int value); - void signalCreateButtonClicked(); void signalProfileRenamed(QString,QString); - void signalProfileChanged(QString,QString); + void signalProfileChangedByUser(QString,QString); void signalProfileDeleted(QString); - void signalProfileAdded(); + void signalAddNewProfile(QString); private slots: @@ -102,7 +98,6 @@ namespace ContentSelectorView void slotAddonTableItemClicked(const QModelIndex &index); void slotUpdateCreateButton (bool); - // void slotUpdateOpenButton(const QStringList &items); // Action slots void on_newProfileAction_triggered(); diff --git a/components/contentselector/view/profilescombobox.cpp b/components/contentselector/view/profilescombobox.cpp index 29001189d..0e9905df4 100644 --- a/components/contentselector/view/profilescombobox.cpp +++ b/components/contentselector/view/profilescombobox.cpp @@ -15,8 +15,8 @@ ContentSelectorView::ProfilesComboBox::ProfilesComboBox(QWidget *parent) : setValidator(mValidator); setCompleter(0); - connect(this, SIGNAL(currentIndexChanged(int)), this, - SLOT(slotIndexChanged(int))); + connect(this, SIGNAL(activated(int)), this, + SLOT(slotIndexChangedByUser(int))); setInsertPolicy(QComboBox::NoInsert); } @@ -85,13 +85,13 @@ void ContentSelectorView::ProfilesComboBox::slotEditingFinished() emit(profileRenamed(previous, current)); } -void ContentSelectorView::ProfilesComboBox::slotIndexChanged(int index) +void ContentSelectorView::ProfilesComboBox::slotIndexChangedByUser(int index) { if (index == -1) return; - emit(profileChanged(mOldProfile, currentText())); - mOldProfile = itemText(index); + emit (signalProfileChanged(mOldProfile, currentText())); + mOldProfile = currentText(); } void ContentSelectorView::ProfilesComboBox::paintEvent(QPaintEvent *) diff --git a/components/contentselector/view/profilescombobox.hpp b/components/contentselector/view/profilescombobox.hpp index 560c42c10..fc87a94b4 100644 --- a/components/contentselector/view/profilescombobox.hpp +++ b/components/contentselector/view/profilescombobox.hpp @@ -14,17 +14,19 @@ namespace ContentSelectorView public: explicit ProfilesComboBox(QWidget *parent = 0); void setEditEnabled(bool editable); - void setPlaceholderText (const QString &text); + void setPlaceholderText(const QString &text); + // void indexChanged(int index); signals: - void signalProfileTextChanged (const QString &item); - void profileChanged(const QString &previous, const QString ¤t); + void signalProfileTextChanged(const QString &item); + void signalProfileChanged(const QString &previous, const QString ¤t); + void signalProfileChanged(int index); void profileRenamed(const QString &oldName, const QString &newName); private slots: void slotEditingFinished(); - void slotIndexChanged(int index); + void slotIndexChangedByUser(int index); void slotTextChanged(const QString &text); private: diff --git a/apps/launcher/utils/textinputdialog.cpp b/components/contentselector/view/textinputdialog.cpp similarity index 75% rename from apps/launcher/utils/textinputdialog.cpp rename to components/contentselector/view/textinputdialog.cpp index 51928c09a..6bb92f113 100644 --- a/apps/launcher/utils/textinputdialog.cpp +++ b/components/contentselector/view/textinputdialog.cpp @@ -16,6 +16,7 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid mButtonBox = new QDialogButtonBox(this); mButtonBox->addButton(QDialogButtonBox::Ok); mButtonBox->addButton(QDialogButtonBox::Cancel); + mButtonBox->button(QDialogButtonBox::Ok)->setEnabled (false); // Line edit QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore @@ -38,11 +39,11 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid Q_UNUSED(title); #endif - setOkButtonEnabled(false); setModal(true); connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(mLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotUpdateOkButton(QString))); } @@ -53,19 +54,23 @@ int TextInputDialog::exec() return QDialog::exec(); } -void TextInputDialog::setOkButtonEnabled(bool enabled) +QString TextInputDialog::getText() const { - QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok); - okButton->setEnabled(enabled); + return mLineEdit->text(); +} - QPalette *palette = new QPalette(); - palette->setColor(QPalette::Text,Qt::red); +void TextInputDialog::slotUpdateOkButton(QString text) +{ + bool enabled = !(text.isEmpty()); + mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(enabled); - if (enabled) { + if (enabled) mLineEdit->setPalette(QApplication::palette()); - } else { + else + { // Existing profile name, make the text red + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Text,Qt::red); mLineEdit->setPalette(*palette); } - } diff --git a/apps/launcher/utils/textinputdialog.hpp b/components/contentselector/view/textinputdialog.hpp similarity index 78% rename from apps/launcher/utils/textinputdialog.hpp rename to components/contentselector/view/textinputdialog.hpp index de3a9fb72..a0b7e350a 100644 --- a/apps/launcher/utils/textinputdialog.hpp +++ b/components/contentselector/view/textinputdialog.hpp @@ -13,18 +13,19 @@ namespace ContentSelectorView { class TextInputDialog : public QDialog { Q_OBJECT -public: - explicit TextInputDialog(const QString& title, const QString &text, QWidget *parent = 0); - inline ContentSelectorView::LineEdit *lineEdit() { return mLineEdit; } - void setOkButtonEnabled(bool enabled); ContentSelectorView::LineEdit *mLineEdit; + QDialogButtonBox *mButtonBox; - int exec(); +public: -private: - QDialogButtonBox *mButtonBox; + explicit TextInputDialog(const QString& title, const QString &text, QWidget *parent = 0); + QString getText() const; + + int exec(); +private slots: + void slotUpdateOkButton(QString text); }; diff --git a/files/ui/datafilespage.ui b/files/ui/datafilespage.ui index 73d7a4902..0cafd606a 100644 --- a/files/ui/datafilespage.ui +++ b/files/ui/datafilespage.ui @@ -7,7 +7,7 @@ 0 0 518 - 424 + 436 @@ -242,11 +242,6 @@ 0 - - - Default - -