diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp new file mode 100644 index 000000000..646d31803 --- /dev/null +++ b/apps/launcher/datafilespage.cpp @@ -0,0 +1,315 @@ +#include + +#include // TODO: Remove + +#include + +#include "datafilespage.hpp" +#include "lineedit.hpp" + +using namespace ESM; + +DataFilesPage::DataFilesPage(QWidget *parent) : QWidget(parent) +{ + mDataFilesModel = new QStandardItemModel(); // Contains all plugins with masters + mPluginsModel = new QStandardItemModel(); // Contains selectable plugins + + mPluginsSelectModel = new QItemSelectionModel(mPluginsModel); + + //QPushButton *deselectButton = new QPushButton(tr("Deselect All")); + QLabel *filterLabel = new QLabel(tr("Filter:"), this); + LineEdit *filterLineEdit = new LineEdit(this); + + QHBoxLayout *topLayout = new QHBoxLayout(); + QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + topLayout->addItem(hSpacer1); + topLayout->addWidget(filterLabel); + topLayout->addWidget(filterLineEdit); + + mMastersWidget = new QTableWidget(this); // Contains the available masters + mPluginsTable = new QTableView(this); + + // Add both tables to a splitter + QSplitter *splitter = new QSplitter(this); + splitter->setOrientation(Qt::Vertical); + + splitter->addWidget(mPluginsTable); + splitter->addWidget(mMastersWidget); + + + // Adjust the default widget heights inside the splitter + QList sizeList; + sizeList << 200 << 400; + splitter->setSizes(sizeList); + + // Bottom part with profile options + QLabel *profileLabel = new QLabel(tr("Current Profile:"), this); + + // TEST + mProfileModel = new QStringListModel(); + QStringList profileList; + profileList << "Default" << "New" << "Yeah" << "Cool story bro!"; + mProfileModel->setStringList(profileList); + + mProfileComboBox = new QComboBox(this); + mProfileComboBox->setModel(mProfileModel); + + mProfileComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + mProfileComboBox->setInsertPolicy(QComboBox::InsertAtBottom); + //mProfileComboBox->addItem(QString("New Profile")); + + QToolButton *NewProfileToolButton = new QToolButton(this); + NewProfileToolButton->setIcon(QIcon::fromTheme("document-new")); + + QToolButton *CopyProfileToolButton = new QToolButton(this); + CopyProfileToolButton->setIcon(QIcon::fromTheme("edit-copy")); + + QToolButton *DeleteProfileToolButton = new QToolButton(this); + DeleteProfileToolButton->setIcon(QIcon::fromTheme("document-close")); + + QHBoxLayout *bottomLayout = new QHBoxLayout(); + + bottomLayout->addWidget(profileLabel); + bottomLayout->addWidget(mProfileComboBox); + bottomLayout->addWidget(NewProfileToolButton); + bottomLayout->addWidget(CopyProfileToolButton); + bottomLayout->addWidget(DeleteProfileToolButton); + + QVBoxLayout *pageLayout = new QVBoxLayout(this); + // Add some space above and below the page items + QSpacerItem *vSpacer1 = new QSpacerItem(5, 5, QSizePolicy::Minimum, QSizePolicy::Minimum); + QSpacerItem *vSpacer2 = new QSpacerItem(5, 5, QSizePolicy::Minimum, QSizePolicy::Minimum); + QSpacerItem *vSpacer3 = new QSpacerItem(5, 5, QSizePolicy::Minimum, QSizePolicy::Minimum); + + //pageLayout->addItem(vSpacer1); + pageLayout->addLayout(topLayout); + pageLayout->addItem(vSpacer2); + pageLayout->addWidget(splitter); + pageLayout->addLayout(bottomLayout); + pageLayout->addItem(vSpacer3); + + setupDataFiles(); + + connect(mMastersWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), this, SLOT(masterSelectionChanged(const QItemSelection&, const QItemSelection&))); + connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckstate(QModelIndex))); + connect(mPluginsModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(resizeRows())); + +} + +void DataFilesPage::setupDataFiles() +{ + mMastersWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + mMastersWidget->setSelectionMode(QAbstractItemView::MultiSelection); + mMastersWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + mMastersWidget->setAlternatingRowColors(true); + mMastersWidget->horizontalHeader()->setStretchLastSection(true); + mMastersWidget->horizontalHeader()->hide(); + mMastersWidget->verticalHeader()->hide(); + mMastersWidget->insertColumn(0); + + mPluginsTable->setModel(mPluginsModel); + mPluginsTable->setSelectionModel(mPluginsSelectModel); + mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + mPluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + mPluginsTable->setAlternatingRowColors(true); + mPluginsTable->horizontalHeader()->setStretchLastSection(true); + mPluginsTable->horizontalHeader()->hide(); + + + mPluginsTable->setDragEnabled(true); + mPluginsTable->setDragDropMode(QAbstractItemView::InternalMove); + mPluginsTable->setDropIndicatorShown(true); + mPluginsTable->setDragDropOverwriteMode(false); + mPluginsTable->viewport()->setAcceptDrops(true); + + mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); + + // Some testing TODO TODO TODO + + QDir dataFilesDir("data/"); + + if (!dataFilesDir.exists()) + qWarning("Cannot find the plugin directory"); + + dataFilesDir.setNameFilters((QStringList() << "*.esp")); // Only load plugins + + QStringList dataFiles = dataFilesDir.entryList(); + + for (int i=0; i itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly); + + if (itemList.isEmpty()) // Master is not yet in the widget + { + mMastersWidget->insertRow(i); + QTableWidgetItem *item = new QTableWidgetItem(currentMaster); + mMastersWidget->setItem(i, 0, item); + } + } + + availableMasters.sort(); // Sort the masters alphabetically + + // Now we put the currentFile in the mDataFilesModel under its masters + QStandardItem *parent = new QStandardItem(availableMasters.join(",")); + QStandardItem *child = new QStandardItem(currentFile); + + QList masterList = mDataFilesModel->findItems(availableMasters.join(",")); + + + if (masterList.isEmpty()) { // Masters node not yet in the mDataFilesModel + parent->appendRow(child); + mDataFilesModel->appendRow(parent); + } else { + // Masters node exists, append current plugin + foreach (QStandardItem *currentItem, masterList) { + currentItem->appendRow(child); + } + } + } +} + +void DataFilesPage::masterSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) +{ + if (mMastersWidget->selectionModel()->hasSelection()) { + const QModelIndexList selectedIndexes = mMastersWidget->selectionModel()->selectedIndexes(); + + QStringList masters; + QString masterstr; + + // Create a QStringList containing all the masters + foreach (const QModelIndex &index, selectedIndexes) { + masters.append(index.data().toString()); + } + + masters.sort(); + masterstr = masters.join(","); // Make a comma-separated QString + + qDebug() << "Masters" << masterstr; + + // Iterate over all masters in the datafilesmodel to see if they are selected + for (int r=0; rrowCount(); ++r) { + QModelIndex currentIndex = mDataFilesModel->index(r, 0); + QString master = currentIndex.data().toString(); + + if (currentIndex.isValid()) { + // See if the current master is in the string with selected masters + if (masterstr.contains(master)) + { + // Append the plugins from the current master to pluginsmodel + addPlugins(currentIndex); + mPluginsTable->resizeRowsToContents(); + } + } + } + } + + // See what plugins to remove + QModelIndexList deselectedIndexes = deselected.indexes(); + + if (!deselectedIndexes.isEmpty()) { + foreach (const QModelIndex ¤tIndex, deselectedIndexes) { + + QString master = currentIndex.data().toString(); + master.prepend("*"); + master.append("*"); + QList itemList = mDataFilesModel->findItems(master, Qt::MatchWildcard); + + if (itemList.isEmpty()) + qDebug() << "Empty as shit"; + + foreach (const QStandardItem *currentItem, itemList) { + + QModelIndex index = currentItem->index(); + qDebug() << "Master to remove plugins of:" << index.data().toString(); + + removePlugins(index); + } + } + } +} + +void DataFilesPage::addPlugins(const QModelIndex &index) +{ + // Find the plugins in the datafilesmodel and append them to the pluginsmodel + if (!index.isValid()) + return; + + for (int r=0; rrowCount(index); ++r ) { + QModelIndex childIndex = index.child(r, 0); + const QString childIndexData = QVariant(mDataFilesModel->data(childIndex)).toString(); + + if (childIndex.isValid()) { + // Now we see if the pluginsmodel already contains this plugin + QList itemList = mPluginsModel->findItems(childIndexData); + + if (itemList.isEmpty()) + { + // Plugin not yet in the pluginsmodel, add it + QStandardItem *item = new QStandardItem(childIndexData); + item->setFlags(item->flags() & ~(Qt::ItemIsDropEnabled)); + item->setCheckable(true); + + mPluginsModel->appendRow(item); + } + } + + } + +} + +void DataFilesPage::removePlugins(const QModelIndex &index) +{ + + if (!index.isValid()) + return; + + for (int r=0; rrowCount(index); ++r) { + QModelIndex childIndex = index.child(r, 0); + + QList itemList = mPluginsModel->findItems(QVariant(childIndex.data()).toString()); + + if (!itemList.isEmpty()) { + foreach (const QStandardItem *currentItem, itemList) { + qDebug() << "Remove plugin:" << currentItem->data(Qt::DisplayRole).toString(); + + mPluginsModel->removeRow(currentItem->row()); + } + } + } + +} + +void DataFilesPage::setCheckstate(QModelIndex index) +{ + if (!index.isValid()) + return; + + if (mPluginsModel->data(index, Qt::CheckStateRole) == Qt::Checked) { + // Selected row is checked, uncheck it + mPluginsModel->setData(index, Qt::Unchecked, Qt::CheckStateRole); + } else { + mPluginsModel->setData(index, Qt::Checked, Qt::CheckStateRole); + } +} + +void DataFilesPage::resizeRows() +{ + // Contents changed + mPluginsTable->resizeRowsToContents(); +} diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp new file mode 100644 index 000000000..689c17ef4 --- /dev/null +++ b/apps/launcher/datafilespage.hpp @@ -0,0 +1,45 @@ +#ifndef DATAFILESPAGE_H +#define DATAFILESPAGE_H + +#include +#include + +class QTableWidget; +class QTableView; +class QComboBox; +class QStandardItemModel; +class QItemSelection; +class QItemSelectionModel; +class QStringListModel; + +class DataFilesPage : public QWidget +{ + Q_OBJECT + +public: + DataFilesPage(QWidget *parent = 0); + + QComboBox *mProfileComboBox; + QStringListModel *mProfileModel; + +public slots: + void masterSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); + void setCheckstate(QModelIndex index); + void resizeRows(); + +private: + QTableWidget *mMastersWidget; + QTableView *mPluginsTable; + + QStandardItemModel *mDataFilesModel; + QStandardItemModel *mPluginsModel; + + QItemSelectionModel *mPluginsSelectModel; + + void setupDataFiles(); + void addPlugins(const QModelIndex &index); + void removePlugins(const QModelIndex &index); + +}; + +#endif diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/apps/launcher/graphicspage.cpp @@ -0,0 +1 @@ + diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/apps/launcher/graphicspage.hpp @@ -0,0 +1 @@ + diff --git a/apps/launcher/lineedit.hpp b/apps/launcher/lineedit.hpp new file mode 100644 index 000000000..7a96a523c --- /dev/null +++ b/apps/launcher/lineedit.hpp @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (c) 2007 Trolltech ASA +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#ifndef LINEEDIT_H +#define LINEEDIT_H + +#include + +class QToolButton; + +class LineEdit : public QLineEdit +{ + Q_OBJECT + +public: + LineEdit(QWidget *parent = 0); + +protected: + void resizeEvent(QResizeEvent *); + +private slots: + void updateCloseButton(const QString &text); + +private: + QToolButton *clearButton; +}; + +#endif // LIENEDIT_H + diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp new file mode 100644 index 000000000..c1b7a6a81 --- /dev/null +++ b/apps/launcher/maindialog.hpp @@ -0,0 +1,36 @@ +#ifndef MAINDIALOG_H +#define MAINDIALOG_H + +#include + +class QListWidget; +class QListWidgetItem; +class QStackedWidget; +class QStringListModel; + +class PlayPage; +class DataFilesPage; + +class MainDialog : public QDialog +{ + Q_OBJECT + +public: + MainDialog(); + + //QStringListModel *mProfileModel; + +public slots: + void changePage(QListWidgetItem *current, QListWidgetItem *previous); + +private: + void createIcons(); + + QListWidget *mIconWidget; + QStackedWidget *mPagesWidget; + + PlayPage *mPlayPage; + DataFilesPage *mDataFilesPage; +}; + +#endif diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp new file mode 100644 index 000000000..18360ffc6 --- /dev/null +++ b/apps/launcher/playpage.cpp @@ -0,0 +1,33 @@ +#include + +#include "playpage.hpp" + +PlayPage::PlayPage(QWidget *parent) : QWidget(parent) +{ + QPushButton *playButton = new QPushButton(tr("Play")); + playButton->setMinimumSize(QSize(150, 50)); + + // TEST + mProfileModel = new QStringListModel(); + QStringList profileList; + profileList << "Other" << "Bla" << "No" << "SEGFAULT!"; + mProfileModel->setStringList(profileList); + + mProfileComboBox = new QComboBox(this); + //mProfileComboBox->setMinimumWidth(200); + mProfileComboBox->setModel(mProfileModel); + + QHBoxLayout *buttonLayout = new QHBoxLayout(); + QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + QSpacerItem *hSpacer2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + buttonLayout->addItem(hSpacer1); + buttonLayout->addWidget(playButton); + buttonLayout->addItem(hSpacer2); + + QVBoxLayout *pageLayout = new QVBoxLayout(this); + + pageLayout->addLayout(buttonLayout); + pageLayout->addWidget(mProfileComboBox); + +} \ No newline at end of file diff --git a/apps/launcher/playpage.hpp b/apps/launcher/playpage.hpp new file mode 100644 index 000000000..dcf7c48f3 --- /dev/null +++ b/apps/launcher/playpage.hpp @@ -0,0 +1,20 @@ +#ifndef PLAYPAGE_H +#define PLAYPAGE_H + +#include + +class QComboBox; +class QStringListModel; + +class PlayPage : public QWidget +{ + Q_OBJECT + +public: + PlayPage(QWidget *parent = 0); + + QComboBox *mProfileComboBox; + QStringListModel *mProfileModel; +}; + +#endif \ No newline at end of file diff --git a/apps/launcher/resources/openmw-header.png b/apps/launcher/resources/openmw-header.png new file mode 100644 index 000000000..a3045ce61 Binary files /dev/null and b/apps/launcher/resources/openmw-header.png differ diff --git a/apps/launcher/resources/openmw-plugin-icon.png b/apps/launcher/resources/openmw-plugin-icon.png new file mode 100644 index 000000000..c34cba554 Binary files /dev/null and b/apps/launcher/resources/openmw-plugin-icon.png differ diff --git a/background.png b/background.png new file mode 100644 index 000000000..b51a97f94 Binary files /dev/null and b/background.png differ