1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-21 12:09:41 +00:00

Merge remote-tracking branch 'graffy76/esxSelector' into saving

This commit is contained in:
Marc Zinnschlag 2013-09-23 10:09:43 +02:00
commit d4b2a6b9f1
72 changed files with 2015 additions and 1519 deletions

View file

@ -167,6 +167,7 @@ if(USE_SYSTEM_TINYXML)
find_library(TINYXML_LIBRARIES tinyxml) find_library(TINYXML_LIBRARIES tinyxml)
find_path(TINYXML_INCLUDE_DIR tinyxml.h) find_path(TINYXML_INCLUDE_DIR tinyxml.h)
message(STATUS "Found TinyXML: ${TINYXML_LIBRARIES} ${TINYXML_INCLUDE_DIR}") message(STATUS "Found TinyXML: ${TINYXML_LIBRARIES} ${TINYXML_INCLUDE_DIR}")
add_definitions (-DTIXML_USE_STL)
if(TINYXML_LIBRARIES AND TINYXML_INCLUDE_DIR) if(TINYXML_LIBRARIES AND TINYXML_INCLUDE_DIR)
include_directories(${TINYXML_INCLUDE_DIR}) include_directories(${TINYXML_INCLUDE_DIR})
message(STATUS "Using system TinyXML library.") message(STATUS "Using system TinyXML library.")

View file

@ -305,14 +305,14 @@ int load(Arguments& info)
info.data.author = esm.getAuthor(); info.data.author = esm.getAuthor();
info.data.description = esm.getDesc(); info.data.description = esm.getDesc();
info.data.masters = esm.getMasters(); info.data.masters = esm.getGameFiles();
if (!quiet) if (!quiet)
{ {
std::cout << "Author: " << esm.getAuthor() << std::endl std::cout << "Author: " << esm.getAuthor() << std::endl
<< "Description: " << esm.getDesc() << std::endl << "Description: " << esm.getDesc() << std::endl
<< "File format version: " << esm.getFVer() << std::endl; << "File format version: " << esm.getFVer() << std::endl;
std::vector<ESM::Header::MasterData> m = esm.getMasters(); std::vector<ESM::Header::MasterData> m = esm.getGameFiles();
if (!m.empty()) if (!m.empty())
{ {
std::cout << "Masters:" << std::endl; std::cout << "Masters:" << std::endl;

View file

@ -4,141 +4,146 @@
#include <QMessageBox> #include <QMessageBox>
#include <QCheckBox> #include <QCheckBox>
#include <QMenu> #include <QMenu>
#include <QSortFilterProxyModel>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/fileorderlist/model/datafilesmodel.hpp> #include <components/contentselector/model/esmfile.hpp>
#include <components/fileorderlist/model/pluginsproxymodel.hpp>
#include <components/fileorderlist/model/esm/esmfile.hpp>
#include <components/fileorderlist/utils/lineedit.hpp> #include <components/contentselector/view/lineedit.hpp>
#include <components/fileorderlist/utils/naturalsort.hpp> #include <components/contentselector/model/naturalsort.hpp>
#include <components/fileorderlist/utils/profilescombobox.hpp> #include <components/contentselector/view/profilescombobox.hpp>
#include "settings/gamesettings.hpp" #include "settings/gamesettings.hpp"
#include "settings/launchersettings.hpp" #include "settings/launchersettings.hpp"
#include "utils/textinputdialog.hpp" #include "utils/textinputdialog.hpp"
#include "components/contentselector/view/contentselector.hpp"
#include "components/contentselector/model/contentmodel.hpp"
#include <QDebug>
DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent) DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent)
: mCfgMgr(cfg) : mCfgMgr(cfg)
, mGameSettings(gameSettings) , mGameSettings(gameSettings)
, mLauncherSettings(launcherSettings) , mLauncherSettings(launcherSettings)
, QWidget(parent)
{ {
setupUi(this); setupUi(this);
// mContentSelector.setParent(parent);
// Models // QMetaObject::connectSlotsByName(this);
mDataFilesModel = new DataFilesModel(this);
mMastersProxyModel = new QSortFilterProxyModel(); projectGroupBox->hide();
mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm"));
mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
mMastersProxyModel->setSourceModel(mDataFilesModel);
mPluginsProxyModel = new PluginsProxyModel();
mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp"));
mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
mPluginsProxyModel->setSourceModel(mDataFilesModel);
mFilterProxyModel = new QSortFilterProxyModel();
mFilterProxyModel->setDynamicSortFilter(true);
mFilterProxyModel->setSourceModel(mPluginsProxyModel);
QCheckBox checkBox;
unsigned int height = checkBox.sizeHint().height() + 4;
mastersTable->setModel(mMastersProxyModel);
mastersTable->setObjectName("MastersTable");
mastersTable->setContextMenuPolicy(Qt::CustomContextMenu);
mastersTable->setSortingEnabled(false);
mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
mastersTable->setAlternatingRowColors(true);
mastersTable->horizontalHeader()->setStretchLastSection(true);
mastersTable->horizontalHeader()->hide();
// Set the row height to the size of the checkboxes
mastersTable->verticalHeader()->setDefaultSectionSize(height);
mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
mastersTable->verticalHeader()->hide();
pluginsTable->setModel(mFilterProxyModel);
pluginsTable->setObjectName("PluginsTable");
pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
pluginsTable->setSortingEnabled(false);
pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
pluginsTable->setAlternatingRowColors(true);
pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
pluginsTable->horizontalHeader()->setStretchLastSection(true);
pluginsTable->horizontalHeader()->hide();
pluginsTable->verticalHeader()->setDefaultSectionSize(height);
pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
// Adjust the tableview widths inside the splitter
QList<int> sizeList;
sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt();
sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt();
splitter->setSizes(sizeList);
// Create a dialog for the new profile name input // Create a dialog for the new profile name input
mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this);
connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString)));
connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
connect(pluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
connect(mastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); buildContentModel();
buildGameFileView();
buildAddonView();
buildProfilesView();
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
connect(splitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter()));
createActions(); createActions();
setupDataFiles(); setupDataFiles();
updateViews();
}
void DataFilesPage::buildContentModel()
{
mContentModel = new ContentSelectorModel::ContentModel();
connect(mContentModel, SIGNAL(layoutChanged()), this, SLOT(updateViews()));
}
void DataFilesPage::buildGameFileView()
{
mGameFileProxyModel = new QSortFilterProxyModel(this);
mGameFileProxyModel->setFilterRegExp(QString::number((int)ContentSelectorModel::ContentType_GameFile));
mGameFileProxyModel->setFilterRole (Qt::UserRole);
mGameFileProxyModel->setSourceModel (mContentModel);
gameFileView->setPlaceholderText(QString("Select a game file..."));
gameFileView->setModel(mGameFileProxyModel);
connect(gameFileView, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentGameFileIndexChanged(int)));
gameFileView->setCurrentIndex(-1);
gameFileView->setCurrentIndex(0);
}
void DataFilesPage::buildAddonView()
{
mAddonProxyModel = new QSortFilterProxyModel(this);
mAddonProxyModel->setFilterRegExp (QString::number((int)ContentSelectorModel::ContentType_Addon));
mAddonProxyModel->setFilterRole (Qt::UserRole);
mAddonProxyModel->setDynamicSortFilter (true);
mAddonProxyModel->setSourceModel (mContentModel);
addonView->setModel(mAddonProxyModel);
connect(addonView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotAddonTableItemClicked(const QModelIndex &)));
}
void DataFilesPage::buildProfilesView()
{
profilesComboBox->setPlaceholderText(QString("Select a profile..."));
connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentProfileIndexChanged(int)));
}
void DataFilesPage::updateViews()
{
// Ensure the columns are hidden because sort() re-enables them
addonView->setColumnHidden(1, true);
addonView->setColumnHidden(2, true);
addonView->setColumnHidden(3, true);
addonView->setColumnHidden(4, true);
addonView->setColumnHidden(5, true);
addonView->setColumnHidden(6, true);
addonView->setColumnHidden(7, true);
addonView->setColumnHidden(8, true);
addonView->resizeColumnsToContents();
}
void ContentSelectorView::ContentSelector::addFiles(const QString &path)
{
mContentModel->addFiles(path);
//mContentModel->sort(3); // Sort by date accessed
gameFileView->setCurrentIndex(-1);
mContentModel->uncheckAll();
} }
void DataFilesPage::createActions() void DataFilesPage::createActions()
{ {
// Add the actions to the toolbuttons // Add the actions to the toolbuttons
newProfileButton->setDefaultAction(newProfileAction); newProfileButton->setDefaultAction(newProfileAction);
deleteProfileButton->setDefaultAction(deleteProfileAction); deleteProfileButton->setDefaultAction(deleteProfileAction);
// Context menu actions
mContextMenu = new QMenu(this);
mContextMenu->addAction(checkAction);
mContextMenu->addAction(uncheckAction);
} }
void DataFilesPage::setupDataFiles() void DataFilesPage::setupDataFiles()
{ {
// Set the encoding to the one found in openmw.cfg or the default // Set the encoding to the one found in openmw.cfg or the default
mDataFilesModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); //mContentSelector.setEncoding(mGameSettings.value(QString("encoding"), QString("win1252")));
QStringList paths = mGameSettings.getDataDirs(); QStringList paths = mGameSettings.getDataDirs();
foreach (const QString &path, paths) { foreach (const QString &path, paths) {
mDataFilesModel->addFiles(path); //mContentSelector.
mContentModel->addFiles(path);
} }
QString dataLocal = mGameSettings.getDataLocal(); QString dataLocal = mGameSettings.getDataLocal();
if (!dataLocal.isEmpty()) if (!dataLocal.isEmpty())
mDataFilesModel->addFiles(dataLocal); //mContentSelector.
mContentModel->addFiles(dataLocal);
// Sort by date accessed for now // Sort by date accessed for now
mDataFilesModel->sort(3); //mContentSelector->sort(3);
QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/"));
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
@ -168,6 +173,7 @@ void DataFilesPage::setupDataFiles()
loadSettings(); loadSettings();
gameFileView->setCurrentIndex(-1);
} }
void DataFilesPage::loadSettings() void DataFilesPage::loadSettings()
@ -177,27 +183,16 @@ void DataFilesPage::loadSettings()
if (profile.isEmpty()) if (profile.isEmpty())
return; return;
mDataFilesModel->uncheckAll(); // mContentSelector.
mContentModel->uncheckAll();
QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly); QStringList gameFiles = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly);
QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly); QStringList addons = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly);
foreach (const QString &master, masters) {
QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(master));
if (index.isValid())
mDataFilesModel->setCheckState(index, Qt::Checked);
}
foreach (const QString &plugin, plugins) {
QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(plugin));
if (index.isValid())
mDataFilesModel->setCheckState(index, Qt::Checked);
}
} }
void DataFilesPage::saveSettings() void DataFilesPage::saveSettings()
{ {
if (mDataFilesModel->rowCount() < 1) if (mContentModel->rowCount() < 1)
return; return;
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
@ -213,17 +208,17 @@ void DataFilesPage::saveSettings()
mGameSettings.remove(QString("master")); mGameSettings.remove(QString("master"));
mGameSettings.remove(QString("plugin")); mGameSettings.remove(QString("plugin"));
QStringList items = mDataFilesModel->checkedItems(); ContentSelectorModel::ContentFileList items = mContentModel->checkedItems();
foreach(const QString &item, items) { foreach(const ContentSelectorModel::EsmFile *item, items) {
if (item.endsWith(QString(".esm"), Qt::CaseInsensitive)) { if (item->gameFiles().size() == 0) {
mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item); mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item->fileName());
mGameSettings.setMultiValue(QString("master"), item); mGameSettings.setMultiValue(QString("master"), item->fileName());
} else if (item.endsWith(QString(".esp"), Qt::CaseInsensitive)) { } else {
mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item); mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item->fileName());
mGameSettings.setMultiValue(QString("plugin"), item); mGameSettings.setMultiValue(QString("plugin"), item->fileName());
} }
} }
@ -242,48 +237,11 @@ void DataFilesPage::updateOkButton(const QString &text)
: mNewProfileDialog->setOkButtonEnabled(false); : mNewProfileDialog->setOkButtonEnabled(false);
} }
void DataFilesPage::updateSplitter()
{
// Sigh, update the saved splitter size in settings only when moved
// Since getting mSplitter->sizes() if page is hidden returns invalid values
QList<int> sizes = splitter->sizes();
mLauncherSettings.setValue(QString("General/MastersTable/width"), QString::number(sizes.at(0)));
mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1)));
}
void DataFilesPage::updateViews()
{
// Ensure the columns are hidden because sort() re-enables them
mastersTable->setColumnHidden(1, true);
mastersTable->setColumnHidden(2, true);
mastersTable->setColumnHidden(3, true);
mastersTable->setColumnHidden(4, true);
mastersTable->setColumnHidden(5, true);
mastersTable->setColumnHidden(6, true);
mastersTable->setColumnHidden(7, true);
mastersTable->setColumnHidden(8, true);
pluginsTable->setColumnHidden(1, true);
pluginsTable->setColumnHidden(2, true);
pluginsTable->setColumnHidden(3, true);
pluginsTable->setColumnHidden(4, true);
pluginsTable->setColumnHidden(5, true);
pluginsTable->setColumnHidden(6, true);
pluginsTable->setColumnHidden(7, true);
pluginsTable->setColumnHidden(8, true);
}
void DataFilesPage::setProfilesComboBoxIndex(int index) void DataFilesPage::setProfilesComboBoxIndex(int index)
{ {
profilesComboBox->setCurrentIndex(index); profilesComboBox->setCurrentIndex(index);
} }
void DataFilesPage::slotCurrentIndexChanged(int index)
{
emit profileChanged(index);
}
QAbstractItemModel* DataFilesPage::profilesComboBoxModel() QAbstractItemModel* DataFilesPage::profilesComboBoxModel()
{ {
return profilesComboBox->model(); return profilesComboBox->model();
@ -330,112 +288,30 @@ void DataFilesPage::on_deleteProfileAction_triggered()
} }
} }
void DataFilesPage::on_checkAction_triggered()
{
if (pluginsTable->hasFocus())
setPluginsCheckstates(Qt::Checked);
if (mastersTable->hasFocus())
setMastersCheckstates(Qt::Checked);
}
void DataFilesPage::on_uncheckAction_triggered()
{
if (pluginsTable->hasFocus())
setPluginsCheckstates(Qt::Unchecked);
if (mastersTable->hasFocus())
setMastersCheckstates(Qt::Unchecked);
}
void DataFilesPage::setMastersCheckstates(Qt::CheckState state)
{
if (!mastersTable->selectionModel()->hasSelection()) {
return;
}
QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes();
foreach (const QModelIndex &index, indexes)
{
if (!index.isValid())
return;
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
if (!sourceIndex.isValid())
return;
mDataFilesModel->setCheckState(sourceIndex, state);
}
}
void DataFilesPage::setPluginsCheckstates(Qt::CheckState state) void DataFilesPage::setPluginsCheckstates(Qt::CheckState state)
{ {
if (!pluginsTable->selectionModel()->hasSelection()) { if (!addonView->selectionModel()->hasSelection()) {
return; return;
} }
QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes(); QModelIndexList indexes = addonView->selectionModel()->selectedIndexes();
foreach (const QModelIndex &index, indexes) foreach (const QModelIndex &index, indexes)
{ {
if (!index.isValid()) if (!index.isValid())
return; return;
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( QModelIndex sourceIndex = mAddonProxyModel->mapToSource(index);
mFilterProxyModel->mapToSource(index));
if (!sourceIndex.isValid()) if (!sourceIndex.isValid())
return; return;
mDataFilesModel->setCheckState(sourceIndex, state); //bool isChecked = ( state == Qt::Checked );
mContentModel->setData(sourceIndex, state, Qt::CheckStateRole);
} }
} }
void DataFilesPage::setCheckState(QModelIndex index)
{
if (!index.isValid())
return;
QObject *object = QObject::sender();
// Not a signal-slot call
if (!object)
return;
if (object->objectName() == QLatin1String("PluginsTable")) {
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
mFilterProxyModel->mapToSource(index));
if (sourceIndex.isValid()) {
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
}
}
if (object->objectName() == QLatin1String("MastersTable")) {
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
if (sourceIndex.isValid()) {
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
}
}
return;
}
void DataFilesPage::filterChanged(const QString filter)
{
QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString);
mFilterProxyModel->setFilterRegExp(regExp);
}
void DataFilesPage::profileChanged(const QString &previous, const QString &current) void DataFilesPage::profileChanged(const QString &previous, const QString &current)
{ {
// Prevent the deletion of the default profile // Prevent the deletion of the default profile
@ -480,72 +356,51 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre
loadSettings(); loadSettings();
} }
////////////////////////////
void DataFilesPage::showContextMenu(const QPoint &point) QStringList DataFilesPage::checkedItemsPaths()
{ {
QObject *object = QObject::sender(); QStringList itemPaths;
// Not a signal-slot call foreach( const ContentSelectorModel::EsmFile *file, mContentModel->checkedItems())
if (!object) itemPaths << file->path();
return;
if (object->objectName() == QLatin1String("PluginsTable")) { return itemPaths;
if (!pluginsTable->selectionModel()->hasSelection()) }
return;
void DataFilesPage::slotCurrentProfileIndexChanged(int index)
QPoint globalPos = pluginsTable->mapToGlobal(point); {
QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes(); emit profileChanged(index);
}
// Show the check/uncheck actions depending on the state of the selected items
uncheckAction->setEnabled(false); void DataFilesPage::slotCurrentGameFileIndexChanged(int index)
checkAction->setEnabled(false); {
static int oldIndex = -1;
foreach (const QModelIndex &index, indexes)
{ QAbstractItemModel *const model = gameFileView->model();
if (!index.isValid()) QSortFilterProxyModel *proxy = dynamic_cast<QSortFilterProxyModel *>(model);
return;
if (proxy)
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( proxy->setDynamicSortFilter(false);
mFilterProxyModel->mapToSource(index));
if (oldIndex > -1)
if (!sourceIndex.isValid()) model->setData(model->index(oldIndex, 0), false, Qt::UserRole + 1);
return;
oldIndex = index;
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
? uncheckAction->setEnabled(true) model->setData(model->index(index, 0), true, Qt::UserRole + 1);
: checkAction->setEnabled(true);
} if (proxy)
proxy->setDynamicSortFilter(true);
// Show menu }
mContextMenu->exec(globalPos);
} void DataFilesPage::slotAddonTableItemClicked(const QModelIndex &index)
{
if (object->objectName() == QLatin1String("MastersTable")) { QAbstractItemModel *const model = addonView->model();
if (!mastersTable->selectionModel()->hasSelection()) //QSortFilterProxyModel *proxy = dynamic_cast<QSortFilterProxyModel *>(model);
return;
if (model->data(index, Qt::CheckStateRole).toInt() == Qt::Unchecked)
QPoint globalPos = mastersTable->mapToGlobal(point); model->setData(index, Qt::Checked, Qt::CheckStateRole);
QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes(); else
model->setData(index, Qt::Unchecked, Qt::CheckStateRole);
// Show the check/uncheck actions depending on the state of the selected items
uncheckAction->setEnabled(false);
checkAction->setEnabled(false);
foreach (const QModelIndex &index, indexes)
{
if (!index.isValid())
return;
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
if (!sourceIndex.isValid())
return;
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
? uncheckAction->setEnabled(true)
: checkAction->setEnabled(true);
}
mContextMenu->exec(globalPos);
}
} }

View file

@ -5,17 +5,17 @@
#include <QModelIndex> #include <QModelIndex>
#include "ui_datafilespage.h" #include "ui_datafilespage.h"
#include "components/contentselector/view/contentselector.hpp"
class QSortFilterProxyModel; class QSortFilterProxyModel;
class QAbstractItemModel; class QAbstractItemModel;
class QAction; class QAction;
class QMenu; class QMenu;
class DataFilesModel;
class TextInputDialog; class TextInputDialog;
class GameSettings; class GameSettings;
class LauncherSettings; class LauncherSettings;
class PluginsProxyModel;
namespace Files { struct ConfigurationManager; } namespace Files { struct ConfigurationManager; }
@ -36,44 +36,33 @@ signals:
void profileChanged(int index); void profileChanged(int index);
public slots: public slots:
void setCheckState(QModelIndex index);
void setProfilesComboBoxIndex(int index); void setProfilesComboBoxIndex(int index);
void filterChanged(const QString filter); //void showContextMenu(const QPoint &point);
void showContextMenu(const QPoint &point);
void profileChanged(const QString &previous, const QString &current); void profileChanged(const QString &previous, const QString &current);
void profileRenamed(const QString &previous, const QString &current); void profileRenamed(const QString &previous, const QString &current);
void updateOkButton(const QString &text); void updateOkButton(const QString &text);
void updateSplitter();
void updateViews(); void updateViews();
// Action slots // Action slots
void on_newProfileAction_triggered(); void on_newProfileAction_triggered();
void on_deleteProfileAction_triggered(); void on_deleteProfileAction_triggered();
void on_checkAction_triggered();
void on_uncheckAction_triggered();
private slots: private slots:
void slotCurrentIndexChanged(int index);
private: private:
DataFilesModel *mDataFilesModel;
PluginsProxyModel *mPluginsProxyModel;
QSortFilterProxyModel *mMastersProxyModel;
QSortFilterProxyModel *mFilterProxyModel;
QMenu *mContextMenu; QMenu *mContextMenu;
//ContentSelectorView::ContentSelector mContentSelector;
ContentSelectorModel::ContentModel *mContentModel;
Files::ConfigurationManager &mCfgMgr; Files::ConfigurationManager &mCfgMgr;
GameSettings &mGameSettings; GameSettings &mGameSettings;
LauncherSettings &mLauncherSettings; LauncherSettings &mLauncherSettings;
TextInputDialog *mNewProfileDialog; TextInputDialog *mNewProfileDialog;
QSortFilterProxyModel *mGameFileProxyModel;
QSortFilterProxyModel *mAddonProxyModel;
void setMastersCheckstates(Qt::CheckState state);
void setPluginsCheckstates(Qt::CheckState state); void setPluginsCheckstates(Qt::CheckState state);
void createActions(); void createActions();
@ -83,6 +72,22 @@ private:
void loadSettings(); void loadSettings();
//////////////////////////////////////
void buildContentModel();
void buildGameFileView();
void buildAddonView();
void buildProfilesView();
//void addFiles(const QString &path);
QStringList checkedItemsPaths();
private slots:
void slotCurrentProfileIndexChanged(int index);
void slotCurrentGameFileIndexChanged(int index);
void slotAddonTableItemClicked(const QModelIndex &index);
}; };
#endif #endif

View file

@ -17,7 +17,7 @@
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/files/ogreplugin.hpp> #include <components/files/ogreplugin.hpp>
#include <components/fileorderlist/utils/naturalsort.hpp> #include <components/contentselector/model/naturalsort.hpp>
#include "settings/graphicssettings.hpp" #include "settings/graphicssettings.hpp"

View file

@ -7,7 +7,7 @@
#include <QValidator> #include <QValidator>
#include <QLabel> #include <QLabel>
#include <components/fileorderlist/utils/lineedit.hpp> #include <components/contentselector/view/lineedit.hpp>
TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWidget *parent) : TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWidget *parent) :
QDialog(parent) QDialog(parent)
@ -19,7 +19,7 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid
// Line edit // Line edit
QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
mLineEdit = new LineEdit(this); mLineEdit = new ContentSelectorView::LineEdit(this);
mLineEdit->setValidator(validator); mLineEdit->setValidator(validator);
mLineEdit->setCompleter(0); mLineEdit->setCompleter(0);

View file

@ -2,20 +2,23 @@
#define TEXTINPUTDIALOG_HPP #define TEXTINPUTDIALOG_HPP
#include <QDialog> #include <QDialog>
//#include "lineedit.hpp"
class QDialogButtonBox; class QDialogButtonBox;
class LineEdit;
namespace ContentSelectorView {
class LineEdit;
}
class TextInputDialog : public QDialog class TextInputDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TextInputDialog(const QString& title, const QString &text, QWidget *parent = 0); explicit TextInputDialog(const QString& title, const QString &text, QWidget *parent = 0);
inline LineEdit *lineEdit() { return mLineEdit; } inline ContentSelectorView::LineEdit *lineEdit() { return mLineEdit; }
void setOkButtonEnabled(bool enabled); void setOkButtonEnabled(bool enabled);
LineEdit *mLineEdit; ContentSelectorView::LineEdit *mLineEdit;
int exec(); int exec();

View file

@ -18,12 +18,12 @@ opencs_hdrs_noqt (model/doc
opencs_units (model/world opencs_units (model/world
idtable idtableproxymodel regionmap idtable idtableproxymodel regionmap data
) )
opencs_units_noqt (model/world opencs_units_noqt (model/world
universalid data record commands columnbase scriptcontext cell refidcollection universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns refidadapter refiddata refidadapterimp ref collectionbase refcollection columns
) )

View file

@ -79,8 +79,8 @@ void CS::Editor::setupDataFiles()
} }
// Set the charset for reading the esm/esp files // Set the charset for reading the esm/esp files
QString encoding = QString::fromStdString(variables["encoding"].as<std::string>()); // QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
mFileDialog.setEncoding(encoding); //mFileDialog.setEncoding(encoding);
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end()); dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());

View file

@ -32,7 +32,7 @@ namespace CS
CSVDoc::StartupDialogue mStartup; CSVDoc::StartupDialogue mStartup;
CSVDoc::NewGameDialogue mNewGame; CSVDoc::NewGameDialogue mNewGame;
CSVSettings::UserSettingsDialog mSettings; CSVSettings::UserSettingsDialog mSettings;
FileDialog mFileDialog; CSVDoc::FileDialog mFileDialog;
Files::ConfigurationManager mCfgMgr; Files::ConfigurationManager mCfgMgr;
boost::filesystem::path mLocal; boost::filesystem::path mLocal;

View file

@ -42,7 +42,7 @@ int main(int argc, char *argv[])
if(!editor.makeIPCServer()) if(!editor.makeIPCServer())
{ {
editor.connectToIPCServer(); editor.connectToIPCServer();
return 0; // return 0;
} }
return editor.run(); return editor.run();

View file

@ -107,6 +107,11 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const; virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const;
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
virtual std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
void addColumn (Column<ESXRecordT> *column); void addColumn (Column<ESXRecordT> *column);
void setRecord (int index, const Record<ESXRecordT>& record); void setRecord (int index, const Record<ESXRecordT>& record);
@ -293,6 +298,21 @@ namespace CSMWorld
return static_cast<int> (mRecords.size()); return static_cast<int> (mRecords.size());
} }
template<typename ESXRecordT, typename IdAccessorT>
std::vector<std::string> Collection<ESXRecordT, IdAccessorT>::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
for (typename std::map<std::string, int>::const_iterator iter = mIndex.begin();
iter!=mIndex.end(); ++iter)
{
if (listDeleted || !mRecords[iter->second].isDeleted())
ids.push_back (IdAccessorT().getId (mRecords[iter->second].get()));
}
return ids;
}
template<typename ESXRecordT, typename IdAccessorT> template<typename ESXRecordT, typename IdAccessorT>
const Record<ESXRecordT>& Collection<ESXRecordT, IdAccessorT>::getRecord (const std::string& id) const const Record<ESXRecordT>& Collection<ESXRecordT, IdAccessorT>::getRecord (const std::string& id) const
{ {

View file

@ -78,8 +78,12 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const = 0; virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const = 0;
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
};
virtual std::vector<std::string> getIds (bool listDeleted = true) const = 0;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
};
} }
#endif #endif

View file

@ -2,6 +2,7 @@
#include "data.hpp" #include "data.hpp"
#include <stdexcept> #include <stdexcept>
#include <algorithm>
#include <QAbstractItemModel> #include <QAbstractItemModel>
@ -15,13 +16,31 @@
#include "columns.hpp" #include "columns.hpp"
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1, void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2) UniversalId::Type type2, bool update)
{ {
mModels.push_back (model); mModels.push_back (model);
mModelIndex.insert (std::make_pair (type1, model)); mModelIndex.insert (std::make_pair (type1, model));
if (type2!=UniversalId::Type_None) if (type2!=UniversalId::Type_None)
mModelIndex.insert (std::make_pair (type2, model)); mModelIndex.insert (std::make_pair (type2, model));
if (update)
{
connect (model, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (dataChanged (const QModelIndex&, const QModelIndex&)));
connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (rowsChanged (const QModelIndex&, int, int)));
connect (model, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
this, SLOT (rowsChanged (const QModelIndex&, int, int)));
}
}
void CSMWorld::Data::appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
bool listDeleted)
{
std::vector<std::string> ids2 = collection.getIds (listDeleted);
ids.insert (ids.end(), ids2.begin(), ids2.end());
} }
CSMWorld::Data::Data() : mRefs (mCells) CSMWorld::Data::Data() : mRefs (mCells)
@ -155,7 +174,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill); addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill, false);
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class);
addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction); addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction);
addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race); addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race);
@ -167,8 +186,8 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell); addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables, addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable); UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference); addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference, false);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter); addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
} }
CSMWorld::Data::~Data() CSMWorld::Data::~Data()
@ -341,7 +360,7 @@ QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{ {
RegionMap *table = 0; RegionMap *table = 0;
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap,
UniversalId::Type_None); UniversalId::Type_None, false);
return table; return table;
} }
throw std::logic_error ("No table model available for " + id.toString()); throw std::logic_error ("No table model available for " + id.toString());
@ -440,3 +459,36 @@ bool CSMWorld::Data::hasId (const std::string& id) const
getCells().searchId (id)!=-1 || getCells().searchId (id)!=-1 ||
getReferenceables().searchId (id)!=-1; getReferenceables().searchId (id)!=-1;
} }
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
appendIds (ids, mGlobals, listDeleted);
appendIds (ids, mGmsts, listDeleted);
appendIds (ids, mClasses, listDeleted);
appendIds (ids, mFactions, listDeleted);
appendIds (ids, mRaces, listDeleted);
appendIds (ids, mSounds, listDeleted);
appendIds (ids, mScripts, listDeleted);
appendIds (ids, mRegions, listDeleted);
appendIds (ids, mBirthsigns, listDeleted);
appendIds (ids, mSpells, listDeleted);
appendIds (ids, mCells, listDeleted);
appendIds (ids, mReferenceables, listDeleted);
std::sort (ids.begin(), ids.end());
return ids;
}
void CSMWorld::Data::dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
if (topLeft.column()<=0)
emit idListChanged();
}
void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
{
emit idListChanged();
}

View file

@ -6,6 +6,9 @@
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <QObject>
#include <QModelIndex>
#include <components/esm/loadglob.hpp> #include <components/esm/loadglob.hpp>
#include <components/esm/loadgmst.hpp> #include <components/esm/loadgmst.hpp>
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
@ -30,8 +33,10 @@ class QAbstractItemModel;
namespace CSMWorld namespace CSMWorld
{ {
class Data class Data : public QObject
{ {
Q_OBJECT
IdCollection<ESM::Global> mGlobals; IdCollection<ESM::Global> mGlobals;
IdCollection<ESM::GameSetting> mGmsts; IdCollection<ESM::GameSetting> mGmsts;
IdCollection<ESM::Skill> mSkills; IdCollection<ESM::Skill> mSkills;
@ -55,13 +60,17 @@ namespace CSMWorld
Data& operator= (const Data&); Data& operator= (const Data&);
void addModel (QAbstractItemModel *model, UniversalId::Type type1, void addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2 = UniversalId::Type_None); UniversalId::Type type2 = UniversalId::Type_None, bool update = true);
static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
bool listDeleted);
///< Append all IDs from collection to \a ids.
public: public:
Data(); Data();
~Data(); virtual ~Data();
const IdCollection<ESM::Global>& getGlobals() const; const IdCollection<ESM::Global>& getGlobals() const;
@ -136,6 +145,21 @@ namespace CSMWorld
///< Merging content of a file into base or modified. ///< Merging content of a file into base or modified.
bool hasId (const std::string& id) const; bool hasId (const std::string& id) const;
std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs that are not internal to the editor.
///
/// \param listDeleted include deleted record in the list
signals:
void idListChanged();
private slots:
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void rowsChanged (const QModelIndex& parent, int start, int end);
}; };
} }

View file

@ -534,3 +534,8 @@ int CSMWorld::RefIdCollection::getAppendIndex (UniversalId::Type type) const
{ {
return mData.getAppendIndex (type); return mData.getAppendIndex (type);
} }
std::vector<std::string> CSMWorld::RefIdCollection::getIds (bool listDeleted) const
{
return mData.getIds (listDeleted);
}

View file

@ -89,6 +89,11 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type) const; virtual int getAppendIndex (UniversalId::Type type) const;
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
virtual std::vector<std::string> getIds (bool listDeleted) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
}; };
} }

View file

@ -196,3 +196,25 @@ int CSMWorld::RefIdData::getSize() const
{ {
return mIndex.size(); return mIndex.size();
} }
std::vector<std::string> CSMWorld::RefIdData::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
for (std::map<std::string, LocalIndex>::const_iterator iter (mIndex.begin()); iter!=mIndex.end();
++iter)
{
if (listDeleted || !getRecord (iter->second).isDeleted())
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator container =
mRecordContainers.find (iter->second.second);
if (container==mRecordContainers.end())
throw std::logic_error ("Invalid referenceable ID type");
ids.push_back (container->second->getId (iter->second.first));
}
}
return ids;
}

View file

@ -182,6 +182,11 @@ namespace CSMWorld
void load (const LocalIndex& index, ESM::ESMReader& reader, bool base); void load (const LocalIndex& index, ESM::ESMReader& reader, bool base);
int getSize() const; int getSize() const;
std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
}; };
} }

View file

@ -1,6 +1,14 @@
#include "scriptcontext.hpp" #include "scriptcontext.hpp"
#include <algorithm>
#include <components/misc/stringops.hpp>
#include "data.hpp"
CSMWorld::ScriptContext::ScriptContext (const Data& data) : mData (data), mIdsUpdated (false) {}
bool CSMWorld::ScriptContext::canDeclareLocals() const bool CSMWorld::ScriptContext::canDeclareLocals() const
{ {
return false; return false;
@ -18,5 +26,19 @@ char CSMWorld::ScriptContext::getMemberType (const std::string& name, const std:
bool CSMWorld::ScriptContext::isId (const std::string& name) const bool CSMWorld::ScriptContext::isId (const std::string& name) const
{ {
return false; if (!mIdsUpdated)
{
mIds = mData.getIds();
std::for_each (mIds.begin(), mIds.end(), &Misc::StringUtils::lowerCase);
mIdsUpdated = true;
}
return std::binary_search (mIds.begin(), mIds.end(), Misc::StringUtils::lowerCase (name));
}
void CSMWorld::ScriptContext::invalidateIds()
{
mIdsUpdated = false;
} }

View file

@ -1,14 +1,25 @@
#ifndef CSM_WORLD_SCRIPTCONTEXT_H #ifndef CSM_WORLD_SCRIPTCONTEXT_H
#define CSM_WORLD_SCRIPTCONTEXT_H #define CSM_WORLD_SCRIPTCONTEXT_H
#include <string>
#include <vector>
#include <components/compiler/context.hpp> #include <components/compiler/context.hpp>
namespace CSMWorld namespace CSMWorld
{ {
class Data;
class ScriptContext : public Compiler::Context class ScriptContext : public Compiler::Context
{ {
const Data& mData;
mutable std::vector<std::string> mIds;
mutable bool mIdsUpdated;
public: public:
ScriptContext (const Data& data);
virtual bool canDeclareLocals() const; virtual bool canDeclareLocals() const;
///< Is the compiler allowed to declare local variables? ///< Is the compiler allowed to declare local variables?
@ -20,6 +31,8 @@ namespace CSMWorld
virtual bool isId (const std::string& name) const; virtual bool isId (const std::string& name) const;
///< Does \a name match an ID, that can be referenced? ///< Does \a name match an ID, that can be referenced?
void invalidateIds();
}; };
} }

View file

@ -43,6 +43,10 @@ boost::filesystem::path CSVDoc::AdjusterWidget::getPath() const
return mResultPath; return mResultPath;
} }
bool CSVDoc::AdjusterWidget::isValid() const
{
return mValid;
}
void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
{ {
QString message; QString message;
@ -88,4 +92,4 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
pixmap (QSize (16, 16))); pixmap (QSize (16, 16)));
emit stateChanged (mValid); emit stateChanged (mValid);
} }

View file

@ -25,6 +25,9 @@ namespace CSVDoc
void setLocalData (const boost::filesystem::path& localData); void setLocalData (const boost::filesystem::path& localData);
QString getText() const;
bool isValid() const;
boost::filesystem::path getPath() const; boost::filesystem::path getPath() const;
///< This function must not be called if there is no valid path. ///< This function must not be called if there is no valid path.
@ -38,4 +41,4 @@ namespace CSVDoc
}; };
} }
#endif #endif

View file

@ -9,145 +9,48 @@
#include <QSpacerItem> #include <QSpacerItem>
#include <QPushButton> #include <QPushButton>
#include <QLabel> #include <QLabel>
#include <QGroupBox>
#include <components/fileorderlist/model/datafilesmodel.hpp> #include <components/contentselector/model/esmfile.hpp>
#include <components/fileorderlist/model/pluginsproxymodel.hpp> #include <components/contentselector/view/lineedit.hpp>
#include <components/fileorderlist/model/esm/esmfile.hpp>
#include <components/fileorderlist/utils/lineedit.hpp> #include "filewidget.hpp"
#include "adjusterwidget.hpp"
FileDialog::FileDialog(QWidget *parent) : #include <QDebug>
QDialog(parent)
CSVDoc::FileDialog::FileDialog(QWidget *parent) :
ContentSelector(parent),
mFileWidget (new FileWidget (this)),
mAdjusterWidget (new AdjusterWidget (this)),
mEnable_1(false),
mEnable_2(false)
{ {
setupUi(this);
// Models
mDataFilesModel = new DataFilesModel(this);
mMastersProxyModel = new QSortFilterProxyModel();
mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm"));
mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
mMastersProxyModel->setSourceModel(mDataFilesModel);
mPluginsProxyModel = new PluginsProxyModel();
mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp"));
mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
mPluginsProxyModel->setSourceModel(mDataFilesModel);
mFilterProxyModel = new QSortFilterProxyModel();
mFilterProxyModel->setDynamicSortFilter(true);
mFilterProxyModel->setSourceModel(mPluginsProxyModel);
QCheckBox checkBox;
unsigned int height = checkBox.sizeHint().height() + 4;
mastersTable->setModel(mMastersProxyModel);
mastersTable->setObjectName("MastersTable");
mastersTable->setContextMenuPolicy(Qt::CustomContextMenu);
mastersTable->setSortingEnabled(false);
mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
mastersTable->setAlternatingRowColors(true);
mastersTable->horizontalHeader()->setStretchLastSection(true);
// Set the row height to the size of the checkboxes
mastersTable->verticalHeader()->setDefaultSectionSize(height);
mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
mastersTable->verticalHeader()->hide();
pluginsTable->setModel(mFilterProxyModel);
pluginsTable->setObjectName("PluginsTable");
pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
pluginsTable->setSortingEnabled(false);
pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
pluginsTable->setAlternatingRowColors(true);
pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
pluginsTable->horizontalHeader()->setStretchLastSection(true);
pluginsTable->verticalHeader()->setDefaultSectionSize(height);
pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
// Hide the profile elements // Hide the profile elements
profileLabel->hide(); profileGroupBox->hide();
profilesComboBox->hide(); addonView->showColumn(2);
newProfileButton->hide();
deleteProfileButton->hide();
// Add some extra widgets resize(400, 400);
QHBoxLayout *nameLayout = new QHBoxLayout();
QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
mNameLabel = new QLabel(tr("File Name:"), this); mFileWidget->setType(true);
mFileWidget->extensionLabelIsVisible(false);
QRegExpValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9\\s]*$")); connect(projectCreateButton, SIGNAL(clicked()), this, SIGNAL(createNewFile()));
mNameLineEdit = new LineEdit(this);
mNameLineEdit->setValidator(validator);
nameLayout->addSpacerItem(spacer); connect(projectButtonBox, SIGNAL(accepted()), this, SIGNAL(openFiles()));
nameLayout->addWidget(mNameLabel); connect(projectButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
nameLayout->addWidget(mNameLineEdit);
mButtonBox = new QDialogButtonBox(this); connect (mFileWidget, SIGNAL (nameChanged (const QString&, bool)),
mAdjusterWidget, SLOT (setName (const QString&, bool)));
mCreateButton = new QPushButton(tr("Create"), this); connect (mAdjusterWidget, SIGNAL (stateChanged (bool)), this, SLOT (slotAdjusterChanged(bool)));
mCreateButton->setEnabled(false); connect (this, SIGNAL (signalGameFileChanged(int)), this, SLOT (slotGameFileSelected(int)));
connect (this, SIGNAL (signalUpdateCreateButton(bool, int)), this, SLOT (slotEnableCreateButton(bool, int)));
verticalLayout->addLayout(nameLayout);
verticalLayout->addWidget(mButtonBox);
// Set sizes
QList<int> sizeList;
sizeList << 175;
sizeList << 200;
splitter->setSizes(sizeList);
resize(600, 400);
connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews()));
connect(mDataFilesModel, SIGNAL(checkedItemsChanged(QStringList)), this, SLOT(updateOpenButton(QStringList)));
connect(mNameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateCreateButton(QString)));
connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
connect(mCreateButton, SIGNAL(clicked()), this, SLOT(createButtonClicked()));
connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
} }
void FileDialog::updateViews() void CSVDoc::FileDialog::updateOpenButton(const QStringList &items)
{ {
// Ensure the columns are hidden because sort() re-enables them QPushButton *openButton = projectButtonBox->button(QDialogButtonBox::Open);
mastersTable->setColumnHidden(1, true);
mastersTable->setColumnHidden(3, true);
mastersTable->setColumnHidden(4, true);
mastersTable->setColumnHidden(5, true);
mastersTable->setColumnHidden(6, true);
mastersTable->setColumnHidden(7, true);
mastersTable->setColumnHidden(8, true);
mastersTable->resizeColumnsToContents();
pluginsTable->setColumnHidden(1, true);
pluginsTable->setColumnHidden(3, true);
pluginsTable->setColumnHidden(4, true);
pluginsTable->setColumnHidden(5, true);
pluginsTable->setColumnHidden(6, true);
pluginsTable->setColumnHidden(7, true);
pluginsTable->setColumnHidden(8, true);
pluginsTable->resizeColumnsToContents();
}
void FileDialog::updateOpenButton(const QStringList &items)
{
QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open);
if (!openButton) if (!openButton)
return; return;
@ -155,118 +58,60 @@ void FileDialog::updateOpenButton(const QStringList &items)
openButton->setEnabled(!items.isEmpty()); openButton->setEnabled(!items.isEmpty());
} }
void FileDialog::updateCreateButton(const QString &name) void CSVDoc::FileDialog::slotEnableCreateButton(bool enable, int widgetNumber)
{ {
if (!mCreateButton->isVisible())
return;
mCreateButton->setEnabled(!name.isEmpty()); if (widgetNumber == 1)
mEnable_1 = enable;
if (widgetNumber == 2)
mEnable_2 = enable;
qDebug() << "update enabled" << mEnable_1 << mEnable_2 << enable;
projectCreateButton->setEnabled(mEnable_1 && mEnable_2);
} }
void FileDialog::filterChanged(const QString &filter) QString CSVDoc::FileDialog::fileName()
{ {
QRegExp filterRe(filter, Qt::CaseInsensitive, QRegExp::FixedString); return mFileWidget->getName();
mFilterProxyModel->setFilterRegExp(filterRe);
} }
void FileDialog::addFiles(const QString &path) void CSVDoc::FileDialog::openFile()
{
mDataFilesModel->addFiles(path);
mDataFilesModel->sort(3); // Sort by date accessed
}
void FileDialog::setEncoding(const QString &encoding)
{
mDataFilesModel->setEncoding(encoding);
}
void FileDialog::setCheckState(QModelIndex index)
{
if (!index.isValid())
return;
QObject *object = QObject::sender();
// Not a signal-slot call
if (!object)
return;
if (object->objectName() == QLatin1String("PluginsTable")) {
QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(
mFilterProxyModel->mapToSource(index));
if (sourceIndex.isValid()) {
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
}
}
if (object->objectName() == QLatin1String("MastersTable")) {
QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index);
if (sourceIndex.isValid()) {
(mDataFilesModel->checkState(sourceIndex) == Qt::Checked)
? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked)
: mDataFilesModel->setCheckState(sourceIndex, Qt::Checked);
}
}
return;
}
QStringList FileDialog::checkedItemsPaths()
{
return mDataFilesModel->checkedItemsPaths();
}
QString FileDialog::fileName()
{
return mNameLineEdit->text();
}
void FileDialog::openFile()
{ {
setWindowTitle(tr("Open")); setWindowTitle(tr("Open"));
mNameLabel->hide(); mFileWidget->hide();
mNameLineEdit->hide(); adjusterWidgetFrame->hide();
mCreateButton->hide(); projectCreateButton->hide();
projectGroupBox->setTitle(tr(""));
mButtonBox->removeButton(mCreateButton); projectButtonBox->button(QDialogButtonBox::Open)->setEnabled(false);
mButtonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Open);
QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open);
openButton->setEnabled(false);
show(); show();
raise(); raise();
activateWindow(); activateWindow();
} }
void FileDialog::newFile() void CSVDoc::FileDialog::newFile()
{ {
setWindowTitle(tr("New")); setWindowTitle(tr("New"));
mNameLabel->show(); fileWidgetFrame->layout()->addWidget(mFileWidget);
mNameLineEdit->clear(); adjusterWidgetFrame->layout()->addWidget(mAdjusterWidget);
mNameLineEdit->show();
mCreateButton->show();
mButtonBox->setStandardButtons(QDialogButtonBox::Cancel); projectButtonBox->setStandardButtons(QDialogButtonBox::Cancel);
mButtonBox->addButton(mCreateButton, QDialogButtonBox::ActionRole); projectButtonBox->addButton(projectCreateButton, QDialogButtonBox::ActionRole);
show(); show();
raise(); raise();
activateWindow(); activateWindow();
} }
void FileDialog::accept() void CSVDoc::FileDialog::slotAdjusterChanged(bool value)
{ {
emit openFiles(); emit signalUpdateCreateButton(mAdjusterWidget->isValid(), 2);
} }
void FileDialog::createButtonClicked() void CSVDoc::FileDialog::slotGameFileSelected(int value)
{ {
emit createNewFile(); emit signalUpdateCreateButton(value > -1, 1);
} }

View file

@ -4,6 +4,7 @@
#include <QDialog> #include <QDialog>
#include <QModelIndex> #include <QModelIndex>
#include "components/contentselector/view/contentselector.hpp"
#include "ui_datafilespage.h" #include "ui_datafilespage.h"
class QDialogButtonBox; class QDialogButtonBox;
@ -13,54 +14,54 @@ class QPushButton;
class QStringList; class QStringList;
class QString; class QString;
class QMenu; class QMenu;
class QLabel;
class DataFilesModel; class DataFilesModel;
class PluginsProxyModel; class PluginsProxyModel;
class FileDialog : public QDialog, private Ui::DataFilesPage namespace ContentSelectorView
{ {
Q_OBJECT class LineEdit;
public: }
explicit FileDialog(QWidget *parent = 0);
void addFiles(const QString &path);
void setEncoding(const QString &encoding);
void openFile(); namespace CSVDoc
void newFile(); {
void accepted(); class FileWidget;
class AdjusterWidget;
QStringList checkedItemsPaths(); class FileDialog : public ContentSelectorView::ContentSelector
QString fileName(); {
Q_OBJECT
signals: FileWidget *mFileWidget;
void openFiles(); AdjusterWidget *mAdjusterWidget;
void createNewFile();
public slots:
void accept();
private slots: bool mEnable_1;
void updateViews(); bool mEnable_2;
void updateOpenButton(const QStringList &items);
void updateCreateButton(const QString &name);
void setCheckState(QModelIndex index);
void filterChanged(const QString &filter); public:
explicit FileDialog(QWidget *parent = 0);
void createButtonClicked(); void openFile();
void newFile();
private: QString fileName();
QLabel *mNameLabel;
LineEdit *mNameLineEdit;
QPushButton *mCreateButton; signals:
QDialogButtonBox *mButtonBox; void openFiles();
void createNewFile();
DataFilesModel *mDataFilesModel; void signalUpdateCreateButton (bool, int);
void signalUpdateCreateButtonFlags(int);
PluginsProxyModel *mPluginsProxyModel; public slots:
QSortFilterProxyModel *mMastersProxyModel;
QSortFilterProxyModel *mFilterProxyModel;
};
private slots:
//void updateViews();
void updateOpenButton(const QStringList &items);
void slotEnableCreateButton(bool enable, int widgetNumber);
void slotAdjusterChanged(bool value);
void slotGameFileSelected(int value);
};
}
#endif // FILEDIALOG_HPP #endif // FILEDIALOG_HPP

View file

@ -50,4 +50,9 @@ QString CSVDoc::FileWidget::getName() const
void CSVDoc::FileWidget::textChanged (const QString& text) void CSVDoc::FileWidget::textChanged (const QString& text)
{ {
emit nameChanged (getName(), mAddon); emit nameChanged (getName(), mAddon);
} }
void CSVDoc::FileWidget::extensionLabelIsVisible(bool visible)
{
mType->setVisible(visible);
}

View file

@ -27,6 +27,8 @@ namespace CSVDoc
QString getName() const; QString getName() const;
void extensionLabelIsVisible(bool visible);
private slots: private slots:
void textChanged (const QString& text); void textChanged (const QString& text);

View file

@ -4,6 +4,7 @@
#include <sstream> #include <sstream>
#include <components/compiler/scanner.hpp> #include <components/compiler/scanner.hpp>
#include <components/compiler/extensions0.hpp>
bool CSVWorld::ScriptHighlighter::parseInt (int value, const Compiler::TokenLoc& loc, bool CSVWorld::ScriptHighlighter::parseInt (int value, const Compiler::TokenLoc& loc,
Compiler::Scanner& scanner) Compiler::Scanner& scanner)
@ -22,7 +23,7 @@ bool CSVWorld::ScriptHighlighter::parseFloat (float value, const Compiler::Token
bool CSVWorld::ScriptHighlighter::parseName (const std::string& name, const Compiler::TokenLoc& loc, bool CSVWorld::ScriptHighlighter::parseName (const std::string& name, const Compiler::TokenLoc& loc,
Compiler::Scanner& scanner) Compiler::Scanner& scanner)
{ {
highlight (loc, Type_Name); highlight (loc, mContext.isId (name) ? Type_Id : Type_Name);
return true; return true;
} }
@ -62,10 +63,10 @@ void CSVWorld::ScriptHighlighter::highlight (const Compiler::TokenLoc& loc, Type
setFormat (index, length, mScheme[type]); setFormat (index, length, mScheme[type]);
} }
CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent) CSVWorld::ScriptHighlighter::ScriptHighlighter (const CSMWorld::Data& data, QTextDocument *parent)
: QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext) : QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext), mContext (data)
{ {
/// \ŧodo replace this with user settings /// \todo replace this with user settings
{ {
QTextCharFormat format; QTextCharFormat format;
format.setForeground (Qt::darkMagenta); format.setForeground (Qt::darkMagenta);
@ -101,6 +102,16 @@ CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent)
format.setForeground (Qt::green); format.setForeground (Qt::green);
mScheme.insert (std::make_pair (Type_Comment, format)); mScheme.insert (std::make_pair (Type_Comment, format));
} }
{
QTextCharFormat format;
format.setForeground (Qt::blue);
mScheme.insert (std::make_pair (Type_Id, format));
}
// configure compiler
Compiler::registerExtensions (mExtensions);
mContext.setExtensions (&mExtensions);
} }
void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text) void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text)
@ -114,5 +125,9 @@ void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text)
scanner.scan (*this); scanner.scan (*this);
} }
catch (...) {} // ignore syntax errors catch (...) {} // ignore syntax errors
}
void CSVWorld::ScriptHighlighter::invalidateIds()
{
mContext.invalidateIds();
} }

View file

@ -7,6 +7,7 @@
#include <components/compiler/nullerrorhandler.hpp> #include <components/compiler/nullerrorhandler.hpp>
#include <components/compiler/parser.hpp> #include <components/compiler/parser.hpp>
#include <components/compiler/extensions.hpp>
#include "../../model/world/scriptcontext.hpp" #include "../../model/world/scriptcontext.hpp"
@ -23,12 +24,14 @@ namespace CSVWorld
Type_Name, Type_Name,
Type_Keyword, Type_Keyword,
Type_Special, Type_Special,
Type_Comment Type_Comment,
Type_Id
}; };
private: private:
Compiler::NullErrorHandler mErrorHandler; Compiler::NullErrorHandler mErrorHandler;
Compiler::Extensions mExtensions;
CSMWorld::ScriptContext mContext; CSMWorld::ScriptContext mContext;
std::map<Type, QTextCharFormat> mScheme; std::map<Type, QTextCharFormat> mScheme;
@ -71,9 +74,11 @@ namespace CSVWorld
public: public:
ScriptHighlighter (QTextDocument *parent); ScriptHighlighter (const CSMWorld::Data& data, QTextDocument *parent);
virtual void highlightBlock (const QString& text); virtual void highlightBlock (const QString& text);
void invalidateIds();
}; };
} }

View file

@ -58,7 +58,13 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc:
connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int))); this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int)));
new ScriptHighlighter (mEditor->document()); connect (&document.getData(), SIGNAL (idListChanged()), this, SLOT (idListChanged()));
mHighlighter = new ScriptHighlighter (document.getData(), mEditor->document());
connect (&mUpdateTimer, SIGNAL (timeout()), this, SLOT (updateHighlighting()));
mUpdateTimer.setSingleShot (true);
} }
void CSVWorld::ScriptSubView::setEditLock (bool locked) void CSVWorld::ScriptSubView::setEditLock (bool locked)
@ -66,8 +72,19 @@ void CSVWorld::ScriptSubView::setEditLock (bool locked)
mEditor->setReadOnly (locked); mEditor->setReadOnly (locked);
} }
void CSVWorld::ScriptSubView::idListChanged()
{
mHighlighter->invalidateIds();
if (!mUpdateTimer.isActive())
mUpdateTimer.start (0);
}
void CSVWorld::ScriptSubView::textChanged() void CSVWorld::ScriptSubView::textChanged()
{ {
if (mChangeLocked)
return;
ChangeLock lock (*this); ChangeLock lock (*this);
mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*mModel, mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*mModel,
@ -79,6 +96,8 @@ void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QMo
if (mChangeLocked) if (mChangeLocked)
return; return;
ChangeLock lock (*this);
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row() && if (index.row()>=topLeft.row() && index.row()<=bottomRight.row() &&
@ -96,4 +115,14 @@ void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, i
if (!parent.isValid() && index.row()>=start && index.row()<=end) if (!parent.isValid() && index.row()>=start && index.row()<=end)
deleteLater(); deleteLater();
}
void CSVWorld::ScriptSubView::updateHighlighting()
{
if (mChangeLocked)
return;
ChangeLock lock (*this);
mHighlighter->rehighlight();
} }

View file

@ -3,6 +3,8 @@
#include "../doc/subview.hpp" #include "../doc/subview.hpp"
#include <QTimer>
class QTextEdit; class QTextEdit;
class QModelIndex; class QModelIndex;
@ -18,6 +20,8 @@ namespace CSMWorld
namespace CSVWorld namespace CSVWorld
{ {
class ScriptHighlighter;
class ScriptSubView : public CSVDoc::SubView class ScriptSubView : public CSVDoc::SubView
{ {
Q_OBJECT Q_OBJECT
@ -27,6 +31,8 @@ namespace CSVWorld
CSMWorld::IdTable *mModel; CSMWorld::IdTable *mModel;
int mColumn; int mColumn;
int mChangeLocked; int mChangeLocked;
ScriptHighlighter *mHighlighter;
QTimer mUpdateTimer;
class ChangeLock class ChangeLock
{ {
@ -49,13 +55,19 @@ namespace CSVWorld
virtual void setEditLock (bool locked); virtual void setEditLock (bool locked);
private slots: public slots:
void idListChanged();
void textChanged(); void textChanged();
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
private slots:
void updateHighlighting();
}; };
} }

View file

@ -119,6 +119,10 @@ target_link_libraries(openmw
components components
) )
if (USE_SYSTEM_TINYXML)
target_link_libraries(openmw ${TINYXML_LIBRARIES})
endif()
if (NOT UNIX) if (NOT UNIX)
target_link_libraries(openmw ${SDL2MAIN_LIBRARY}) target_link_libraries(openmw ${SDL2MAIN_LIBRARY})
endif() endif()

View file

@ -396,6 +396,8 @@ namespace MWBase
/// It only applies to the current form the NPC is in. /// It only applies to the current form the NPC is in.
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) = 0; virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) = 0;
virtual bool getGodModeState() = 0;
virtual bool toggleGodMode() = 0; virtual bool toggleGodMode() = 0;
}; };
} }

View file

@ -250,6 +250,7 @@ namespace MWGui
// remove object from the container it was coming from // remove object from the container it was coming from
mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount); mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount);
mDragAndDrop->finish(); mDragAndDrop->finish();
mDragAndDrop->mSourceModel->update();
} }
else else
{ {

View file

@ -585,7 +585,7 @@ namespace MWInput
mPlayer->pitch(-y/scale); mPlayer->pitch(-y/scale);
} }
if (arg.zrel) if (arg.zrel && mControlSwitch["playerviewswitch"]) //Check to make sure you are allowed to zoomout and there is a change
{ {
MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.zrel); MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.zrel);
MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true); MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true);

View file

@ -275,9 +275,8 @@ namespace MWMechanics
continue; continue;
} }
// workaround: always keep player alive for now // If it's the player and God Mode is turned on, keep it alive
// \todo remove workaround, once player death can be handled if(iter->first.getRefData().getHandle()=="player" && MWBase::Environment::get().getWorld()->getGodModeState())
if(iter->first.getRefData().getHandle()=="player")
{ {
MWMechanics::DynamicStat<float> stat(stats.getHealth()); MWMechanics::DynamicStat<float> stat(stats.getHealth());

View file

@ -151,8 +151,7 @@ namespace MWMechanics
for (Collection::const_iterator iter (prev.begin()); iter!=prev.end(); ++iter) for (Collection::const_iterator iter (prev.begin()); iter!=prev.end(); ++iter)
{ {
Collection::const_iterator other = now.mCollection.find (iter->first); Collection::const_iterator other = now.mCollection.find (iter->first);
if (other==now.end())
if (other==prev.end())
{ {
result.add (iter->first, EffectParam() - iter->second); result.add (iter->first, EffectParam() - iter->second);
} }

View file

@ -726,8 +726,7 @@ namespace MWScript
bool enabled = MWBase::Environment::get().getWorld()->toggleGodMode(); bool enabled = MWBase::Environment::get().getWorld()->toggleGodMode();
// context.report (enabled ? "God Mode -> On" : "God Mode -> Off"); context.report (enabled ? "God Mode -> On" : "God Mode -> Off");
context.report("Unimplemented");
} }
}; };

View file

@ -36,7 +36,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
// all files/readers used by the engine. This will greaty accelerate // all files/readers used by the engine. This will greaty accelerate
// refnumber mangling, as required for handling moved references. // refnumber mangling, as required for handling moved references.
int index = ~0; int index = ~0;
const std::vector<ESM::Header::MasterData> &masters = esm.getMasters(); const std::vector<ESM::Header::MasterData> &masters = esm.getGameFiles();
std::vector<ESM::ESMReader> *allPlugins = esm.getGlobalReaderList(); std::vector<ESM::ESMReader> *allPlugins = esm.getGlobalReaderList();
for (size_t j = 0; j < masters.size(); j++) { for (size_t j = 0; j < masters.size(); j++) {
ESM::Header::MasterData &mast = const_cast<ESM::Header::MasterData&>(masters[j]); ESM::Header::MasterData &mast = const_cast<ESM::Header::MasterData&>(masters[j]);

View file

@ -170,7 +170,7 @@ namespace MWWorld
mSky (true), mCells (mStore, mEsm), mSky (true), mCells (mStore, mEsm),
mActivationDistanceOverride (mActivationDistanceOverride), mActivationDistanceOverride (mActivationDistanceOverride),
mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true), mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true),
mFacedDistance(FLT_MAX) mFacedDistance(FLT_MAX), mGodMode(false)
{ {
mPhysics = new PhysicsSystem(renderer); mPhysics = new PhysicsSystem(renderer);
mPhysEngine = mPhysics->getEngine(); mPhysEngine = mPhysics->getEngine();
@ -1948,9 +1948,16 @@ namespace MWWorld
stats.getSkill(ESM::Skill::Acrobatics).setModified(gmst.find("fWerewolfAcrobatics")->getFloat(), 0); stats.getSkill(ESM::Skill::Acrobatics).setModified(gmst.find("fWerewolfAcrobatics")->getFloat(), 0);
} }
bool World::getGodModeState()
{
return mGodMode;
}
bool World::toggleGodMode() bool World::toggleGodMode()
{ {
return false; mGodMode = !mGodMode;
return mGodMode;
} }
} }

View file

@ -68,6 +68,8 @@ namespace MWWorld
OEngine::Physic::PhysicEngine* mPhysEngine; OEngine::Physic::PhysicEngine* mPhysEngine;
bool mGodMode;
// not implemented // not implemented
World (const World&); World (const World&);
World& operator= (const World&); World& operator= (const World&);
@ -440,6 +442,8 @@ namespace MWWorld
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor); virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor);
virtual bool getGodModeState();
virtual bool toggleGodMode(); virtual bool toggleGodMode();
}; };
} }

View file

@ -1,5 +1,5 @@
project (Components) project (Components)
set (CMAKE_BUILD_TYPE DEBUG)
# source files # source files
add_component_dir (settings add_component_dir (settings
@ -74,21 +74,26 @@ add_component_dir (loadinglistener
loadinglistener loadinglistener
) )
set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/datafilespage.ui
)
find_package(Qt4 COMPONENTS QtCore QtGui) find_package(Qt4 COMPONENTS QtCore QtGui)
if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY)
add_component_qt_dir (fileorderlist add_component_qt_dir (contentselector
model/modelitem model/datafilesmodel model/pluginsproxymodel model/esm/esmfile model/modelitem model/esmfile
utils/profilescombobox utils/comboboxlineedit utils/lineedit utils/naturalsort model/naturalsort model/contentmodel
view/profilescombobox view/comboboxlineedit
view/lineedit view/contentselector
) )
include(${QT_USE_FILE}) include(${QT_USE_FILE})
QT4_WRAP_UI(ESM_UI_HDR ${ESM_UI})
QT4_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES}) QT4_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES})
endif(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) endif(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY)
include_directories(${BULLET_INCLUDE_DIRS}) include_directories(${BULLET_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS}) add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS} ${ESM_UI_HDR})
target_link_libraries(components ${Boost_LIBRARIES} ${OGRE_LIBRARIES}) target_link_libraries(components ${Boost_LIBRARIES} ${OGRE_LIBRARIES})

View file

@ -0,0 +1,478 @@
#include "contentmodel.hpp"
#include "esmfile.hpp"
#include <QDir>
#include <QTextCodec>
#include <components/esm/esmreader.hpp>
#include <QDebug>
ContentSelectorModel::ContentModel::ContentModel(QObject *parent) :
QAbstractTableModel(parent),
mMimeType ("application/omwcontent"),
mMimeTypes (QStringList() << mMimeType),
mColumnCount (1),
mDragDropFlags (Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled),
mDefaultFlags (Qt::ItemIsDropEnabled | Qt::ItemIsSelectable),
mDropActions (Qt::CopyAction | Qt::MoveAction)
{
// setEncoding ("win1252");
uncheckAll();
}
/*
void ContentSelectorModel::ContentModel::setEncoding(const QString &encoding)
{
if (encoding == QLatin1String("win1252"))
mCodec = QTextCodec::codecForName("windows-1252");
else if (encoding == QLatin1String("win1251"))
mCodec = QTextCodec::codecForName("windows-1251");
else if (encoding == QLatin1String("win1250"))
mCodec = QTextCodec::codecForName("windows-1250");
else
return; // This should never happen;
}
*/
int ContentSelectorModel::ContentModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return mColumnCount;
}
int ContentSelectorModel::ContentModel::rowCount(const QModelIndex &parent) const
{
if(parent.isValid())
return 0;
return mFiles.size();
}
const ContentSelectorModel::EsmFile *ContentSelectorModel::ContentModel::item(int row) const
{
if (row >= 0 && row < mFiles.size())
return mFiles.at(row);
return 0;
}
ContentSelectorModel::EsmFile *ContentSelectorModel::ContentModel::item(int row)
{
if (row >= 0 && row < mFiles.count())
return mFiles.at(row);
return 0;
}
const ContentSelectorModel::EsmFile *ContentSelectorModel::ContentModel::findItem(const QString &name) const
{
foreach (const EsmFile *file, mFiles)
{
if (name == file->fileName())
return file;
}
return 0;
}
QModelIndex ContentSelectorModel::ContentModel::indexFromItem(const EsmFile *item) const
{
//workaround: non-const pointer cast for calls from outside contentmodel/contentselector
EsmFile *non_const_file_ptr = const_cast<EsmFile *>(item);
if (item)
return index(mFiles.indexOf(non_const_file_ptr),0);
return QModelIndex();
}
Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
const EsmFile *file = item(index.row());
if (!file)
return Qt::NoItemFlags;
if (canBeChecked(file))
return Qt::ItemIsEnabled | mDragDropFlags | mDefaultFlags;
return mDefaultFlags;
}
QVariant ContentSelectorModel::ContentModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row() >= mFiles.size())
return QVariant();
const EsmFile *file = item(index.row());
if (!file)
return QVariant();
const int column = index.column();
switch (role)
{
case Qt::EditRole:
case Qt::DisplayRole:
{
if (column >=0 && column <=EsmFile::FileProperty_GameFile)
return file->fileProperty(static_cast<const EsmFile::FileProperty>(column));
return QVariant();
break;
}
case Qt::TextAlignmentRole:
{
switch (column)
{
case 0:
case 1:
return Qt::AlignLeft + Qt::AlignVCenter;
case 2:
case 3:
return Qt::AlignRight + Qt::AlignVCenter;
default:
return Qt::AlignLeft + Qt::AlignVCenter;
}
return QVariant();
break;
}
case Qt::ToolTipRole:
{
if (column != 0)
return QVariant();
return file->toolTip();
break;
}
case Qt::CheckStateRole:
{
if (!file->isGameFile())
return isChecked(file->fileName());
break;
}
case Qt::UserRole:
{
if (file->isGameFile())
return ContentType_GameFile;
else
if (flags(index) & Qt::ItemIsEnabled)
return ContentType_Addon;
break;
}
case Qt::UserRole + 1:
return isChecked(file->fileName());
break;
}
return QVariant();
}
bool ContentSelectorModel::ContentModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(!index.isValid())
return false;
EsmFile *file = item(index.row());
QString fileName = file->fileName();
bool success = false;
switch(role)
{
case Qt::EditRole:
{
QStringList list = value.toStringList();
for (int i = 0; i < EsmFile::FileProperty_GameFile; i++)
file->setFileProperty(static_cast<EsmFile::FileProperty>(i), list.at(i));
for (int i = EsmFile::FileProperty_GameFile; i < list.size(); i++)
file->setFileProperty (EsmFile::FileProperty_GameFile, list.at(i));
emit dataChanged(index, index);
success = true;
}
break;
case Qt::UserRole+1:
{
setCheckState(fileName, value.toBool());
emit dataChanged(index, index);
foreach (EsmFile *file, mFiles)
{
if (file->gameFiles().contains(fileName))
{
QModelIndex idx = indexFromItem(file);
emit dataChanged(idx, idx);
}
}
success = true;
}
break;
case Qt::CheckStateRole:
{
int checkValue = value.toInt();
bool success = false;
bool setState = false;
if ((checkValue==Qt::Checked) && !isChecked(fileName))
{
setState = true;
success = true;
}
else if ((checkValue == Qt::Checked) && isChecked (fileName))
setState = true;
else if (checkValue == Qt::Unchecked)
setState = true;
if (setState)
{
setCheckState(fileName, success);
emit dataChanged(index, index);
}
else
return success;
foreach (EsmFile *file, mFiles)
{
if (file->gameFiles().contains(fileName))
{
QModelIndex idx = indexFromItem(file);
emit dataChanged(idx, idx);
}
}
success = true;
}
break;
}
return success;
}
bool ContentSelectorModel::ContentModel::insertRows(int position, int rows, const QModelIndex &parent)
{
if (parent.isValid())
return false;
beginInsertRows(parent, position, position+rows-1);
{
for (int row = 0; row < rows; ++row)
mFiles.insert(position, new EsmFile);
} endInsertRows();
return true;
}
bool ContentSelectorModel::ContentModel::removeRows(int position, int rows, const QModelIndex &parent)
{
if (parent.isValid())
return false;
beginRemoveRows(parent, position, position+rows-1);
{
for (int row = 0; row < rows; ++row)
delete mFiles.takeAt(position);
} endRemoveRows();
return true;
}
Qt::DropActions ContentSelectorModel::ContentModel::supportedDropActions() const
{
return mDropActions;
}
QStringList ContentSelectorModel::ContentModel::mimeTypes() const
{
return mMimeTypes;
}
QMimeData *ContentSelectorModel::ContentModel::mimeData(const QModelIndexList &indexes) const
{
QByteArray encodedData;
foreach (const QModelIndex &index, indexes)
{
if (!index.isValid())
continue;
encodedData.append(item(index.row())->encodedData());
}
QMimeData *mimeData = new QMimeData();
mimeData->setData(mMimeType, encodedData);
return mimeData;
}
bool ContentSelectorModel::ContentModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
if (action == Qt::IgnoreAction)
return true;
if (column > 0)
return false;
if (!data->hasFormat(mMimeType))
return false;
int beginRow = rowCount();
if (row != -1)
beginRow = row;
else if (parent.isValid())
beginRow = parent.row();
QByteArray encodedData = data->data(mMimeType);
QDataStream stream(&encodedData, QIODevice::ReadOnly);
while (!stream.atEnd())
{
QString value;
QStringList values;
QStringList gamefiles;
for (int i = 0; i < EsmFile::FileProperty_GameFile; ++i)
{
stream >> value;
values << value;
}
stream >> gamefiles;
insertRows(beginRow, 1);
QModelIndex idx = index(beginRow++, 0, QModelIndex());
setData(idx, QStringList() << values << gamefiles, Qt::EditRole);
}
return true;
}
bool ContentSelectorModel::ContentModel::canBeChecked(const EsmFile *file) const
{
//element can be checked if all its dependencies are
foreach (const QString &gamefile, file->gameFiles())
if (!isChecked(gamefile))
return false;
return true;
}
void ContentSelectorModel::ContentModel::addFile(EsmFile *file)
{
beginInsertRows(QModelIndex(), mFiles.count(), mFiles.count());
mFiles.append(file);
endInsertRows();
}
void ContentSelectorModel::ContentModel::addFiles(const QString &path)
{
QDir dir(path);
QStringList filters;
filters << "*.esp" << "*.esm" << "*.omwgame" << "*.omwaddon";
dir.setNameFilters(filters);
QTextCodec *codec = QTextCodec::codecForName("UTF8");
// Create a decoder for non-latin characters in esx metadata
QTextDecoder *decoder = codec->makeDecoder();
foreach (const QString &path, dir.entryList())
{
QFileInfo info(dir.absoluteFilePath(path));
EsmFile *file = new EsmFile(path);
try {
ESM::ESMReader fileReader;
ToUTF8::Utf8Encoder encoder(); //ToUTF8::calculateEncoding(QString(mCodec->name()).toStdString()));
//fileReader.setEncoder(&encoder);
fileReader.open(dir.absoluteFilePath(path).toStdString());
foreach (const ESM::Header::MasterData &item, fileReader.getGameFiles())
file->addGameFile(QString::fromStdString(item.name));
file->setAuthor (decoder->toUnicode(fileReader.getAuthor().c_str()));
file->setDate (info.lastModified());
file->setFormat (fileReader.getFormat());
file->setPath (info.absoluteFilePath());
file->setDescription(decoder->toUnicode(fileReader.getDesc().c_str()));
// Put the file in the table
if (findItem(path) == 0)
addFile(file);
} catch(std::runtime_error &e) {
// An error occurred while reading the .esp
qWarning() << "Error reading addon file: " << e.what();
continue;
}
}
delete decoder;
}
bool ContentSelectorModel::ContentModel::isChecked(const QString& name) const
{
if (mCheckStates.contains(name))
return (mCheckStates[name] == Qt::Checked);
return false;
}
void ContentSelectorModel::ContentModel::setCheckState(const QString &name, bool isChecked)
{
if (name.isEmpty())
return;
Qt::CheckState state = Qt::Unchecked;
if (isChecked)
state = Qt::Checked;
mCheckStates[name] = state;
}
ContentSelectorModel::ContentFileList ContentSelectorModel::ContentModel::checkedItems() const
{
ContentFileList list;
foreach (EsmFile *file, mFiles)
{
if (isChecked(file->fileName()))
list << file;
}
return list;
}
void ContentSelectorModel::ContentModel::uncheckAll()
{
emit layoutAboutToBeChanged();
mCheckStates.clear();
emit layoutChanged();
}

View file

@ -0,0 +1,73 @@
#ifndef CONTENTMODEL_HPP
#define CONTENTMODEL_HPP
#include <QAbstractTableModel>
#include <QStringList>
namespace ContentSelectorModel
{
class EsmFile;
typedef QList<EsmFile *> ContentFileList;
enum ContentType
{
ContentType_GameFile,
ContentType_Addon
};
class ContentModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit ContentModel(QObject *parent = 0);
//void setEncoding(const QString &encoding);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
Qt::DropActions supportedDropActions() const;
QStringList mimeTypes() const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
void addFiles(const QString &path);
QModelIndex indexFromItem(const EsmFile *item) const;
const EsmFile *findItem(const QString &name) const;
bool isChecked(const QString &name) const;
void setCheckState(const QString &name, bool isChecked);
ContentFileList checkedItems() const;
void uncheckAll();
private:
void addFile(EsmFile *file);
const EsmFile *item(int row) const;
EsmFile *item(int row);
bool canBeChecked(const EsmFile *file) const;
ContentFileList mFiles;
QHash<QString, Qt::CheckState> mCheckStates;
QTextCodec *mCodec;
public:
QString mMimeType;
QStringList mMimeTypes;
int mColumnCount;
Qt::ItemFlags mDragDropFlags;
Qt::ItemFlags mDefaultFlags;
Qt::DropActions mDropActions;
};
}
#endif // CONTENTMODEL_HPP

View file

@ -0,0 +1,136 @@
#include "esmfile.hpp"
#include <QMimeData>
#include <QDataStream>
int ContentSelectorModel::EsmFile::sPropertyCount = 7;
QString ContentSelectorModel::EsmFile::sToolTip = QString("<b>Author:</b> %1<br/> \
<b>Version:</b> %2<br/> \
<br/><b>Description:</b><br/>%3<br/> \
<br/><b>Dependencies: </b>%4<br/>");
ContentSelectorModel::EsmFile::EsmFile(QString fileName, ModelItem *parent)
: ModelItem(parent), mFileName(fileName), mFormat(0)
{}
void ContentSelectorModel::EsmFile::setFileName(const QString &fileName)
{
mFileName = fileName;
}
void ContentSelectorModel::EsmFile::setAuthor(const QString &author)
{
mAuthor = author;
}
void ContentSelectorModel::EsmFile::setDate(const QDateTime &modified)
{
mModified = modified;
}
void ContentSelectorModel::EsmFile::setFormat(int format)
{
mFormat = format;
}
void ContentSelectorModel::EsmFile::setPath(const QString &path)
{
mPath = path;
}
void ContentSelectorModel::EsmFile::setGameFiles(const QStringList &gamefiles)
{
mGameFiles = gamefiles;
}
void ContentSelectorModel::EsmFile::setDescription(const QString &description)
{
mDescription = description;
}
QByteArray ContentSelectorModel::EsmFile::encodedData() const
{
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
stream << mFileName << mAuthor << QString::number(mFormat)
<< mModified.toString() << mPath << mDescription
<< mGameFiles;
return encodedData;
}
QVariant ContentSelectorModel::EsmFile::fileProperty(const FileProperty prop) const
{
switch (prop)
{
case FileProperty_FileName:
return mFileName;
break;
case FileProperty_Author:
return mAuthor;
break;
case FileProperty_Format:
return mFormat;
break;
case FileProperty_DateModified:
return mModified.toString(Qt::ISODate);
break;
case FileProperty_Path:
return mPath;
break;
case FileProperty_Description:
return mDescription;
break;
case FileProperty_GameFile:
return mGameFiles;
break;
default:
break;
}
return QVariant();
}
void ContentSelectorModel::EsmFile::setFileProperty (const FileProperty prop, const QString &value)
{
switch (prop)
{
case FileProperty_FileName:
mFileName = value;
break;
case FileProperty_Author:
mAuthor = value;
break;
case FileProperty_Format:
mFormat = value.toInt();
break;
case FileProperty_DateModified:
mModified = QDateTime::fromString(value);
break;
case FileProperty_Path:
mPath = value;
break;
case FileProperty_Description:
mDescription = value;
break;
case FileProperty_GameFile:
mGameFiles << value;
break;
default:
break;
}
}

View file

@ -0,0 +1,85 @@
#ifndef ESMFILE_HPP
#define ESMFILE_HPP
#include <QDateTime>
#include <QStringList>
#include "modelitem.hpp"
class QMimeData;
namespace ContentSelectorModel
{
class EsmFile : public ModelItem
{
Q_OBJECT
Q_PROPERTY(QString filename READ fileName)
public:
enum FileProperty
{
FileProperty_FileName = 0,
FileProperty_Author = 1,
FileProperty_Format = 2,
FileProperty_DateModified = 3,
FileProperty_Path = 4,
FileProperty_Description = 5,
FileProperty_GameFile = 6
};
EsmFile(QString fileName = QString(), ModelItem *parent = 0);
// EsmFile(const EsmFile &);
~EsmFile()
{}
void setFileProperty (const FileProperty prop, const QString &value);
void setFileName(const QString &fileName);
void setAuthor(const QString &author);
void setSize(const int size);
void setDate(const QDateTime &modified);
void setFormat(const int format);
void setPath(const QString &path);
void setGameFiles(const QStringList &gameFiles);
void setDescription(const QString &description);
inline void addGameFile (const QString &name) {mGameFiles.append(name); }
QVariant fileProperty (const FileProperty prop) const;
inline QString fileName() const { return mFileName; }
inline QString author() const { return mAuthor; }
inline QDateTime modified() const { return mModified; }
inline float format() const { return mFormat; }
inline QString path() const { return mPath; }
inline const QStringList &gameFiles() const { return mGameFiles; }
inline QString description() const { return mDescription; }
inline QString toolTip() const { return sToolTip.arg(mAuthor)
.arg(mFormat)
.arg(mDescription)
.arg(mGameFiles.join(", "));
}
inline bool isGameFile() const { return (mGameFiles.size() == 0); }
QByteArray encodedData() const;
public:
static int sPropertyCount;
static QString sToolTip;
private:
QString mFileName;
QString mAuthor;
QDateTime mModified;
int mFormat;
QString mPath;
QStringList mGameFiles;
QString mDescription;
QString mToolTip;
};
}
#endif

View file

@ -0,0 +1,69 @@
#include "modelitem.hpp"
ContentSelectorModel::ModelItem::ModelItem(ModelItem *parent)
: mParentItem(parent)
{
}
/*
ContentSelectorModel::ModelItem::ModelItem(const ModelItem *parent)
// : mParentItem(parent)
{
}
*/
ContentSelectorModel::ModelItem::~ModelItem()
{
qDeleteAll(mChildItems);
}
ContentSelectorModel::ModelItem *ContentSelectorModel::ModelItem::parent() const
{
return mParentItem;
}
bool ContentSelectorModel::ModelItem::hasFormat(const QString &mimetype) const
{
if (mimetype == "application/omwcontent")
return true;
return QMimeData::hasFormat(mimetype);
}
int ContentSelectorModel::ModelItem::row() const
{
if (mParentItem)
return 1;
//return mParentItem->childRow(const_cast<ModelItem*>(this));
//return mParentItem->mChildItems.indexOf(const_cast<ModelItem*>(this));
return -1;
}
int ContentSelectorModel::ModelItem::childCount() const
{
return mChildItems.count();
}
int ContentSelectorModel::ModelItem::childRow(ModelItem *child) const
{
Q_ASSERT(child);
return mChildItems.indexOf(child);
}
ContentSelectorModel::ModelItem *ContentSelectorModel::ModelItem::child(int row)
{
return mChildItems.value(row);
}
void ContentSelectorModel::ModelItem::appendChild(ModelItem *item)
{
mChildItems.append(item);
}
void ContentSelectorModel::ModelItem::removeChild(int row)
{
mChildItems.removeAt(row);
}

View file

@ -0,0 +1,39 @@
#ifndef MODELITEM_HPP
#define MODELITEM_HPP
#include <QMimeData>
#include <QList>
namespace ContentSelectorModel
{
class ModelItem : public QMimeData
{
Q_OBJECT
public:
ModelItem(ModelItem *parent = 0);
//ModelItem(const ModelItem *parent = 0);
~ModelItem();
ModelItem *parent() const;
int row() const;
int childCount() const;
int childRow(ModelItem *child) const;
ModelItem *child(int row);
void appendChild(ModelItem *child);
void removeChild(int row);
bool hasFormat(const QString &mimetype) const;
//virtual bool acceptChild(ModelItem *child);
protected:
ModelItem *mParentItem;
QList<ModelItem*> mChildItems;
};
}
#endif

View file

@ -0,0 +1,11 @@
#ifndef NATURALSORT_H
#define NATURALSORT_H
#include <QString>
bool naturalSortLessThanCS( const QString &left, const QString &right );
bool naturalSortLessThanCI( const QString &left, const QString &right );
bool naturalSortGreaterThanCS( const QString &left, const QString &right );
bool naturalSortGreaterThanCI( const QString &left, const QString &right );
#endif

View file

@ -3,7 +3,7 @@
#include "comboboxlineedit.hpp" #include "comboboxlineedit.hpp"
ComboBoxLineEdit::ComboBoxLineEdit(QWidget *parent) ContentSelectorView::ComboBoxLineEdit::ComboBoxLineEdit(QWidget *parent)
: QLineEdit(parent) : QLineEdit(parent)
{ {
mClearButton = new QToolButton(this); mClearButton = new QToolButton(this);
@ -21,7 +21,7 @@ ComboBoxLineEdit::ComboBoxLineEdit(QWidget *parent)
setStyleSheet(QString("ComboBoxLineEdit { background-color: transparent; padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); setStyleSheet(QString("ComboBoxLineEdit { background-color: transparent; padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1));
} }
void ComboBoxLineEdit::resizeEvent(QResizeEvent *) void ContentSelectorView::ComboBoxLineEdit::resizeEvent(QResizeEvent *)
{ {
QSize sz = mClearButton->sizeHint(); QSize sz = mClearButton->sizeHint();
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
@ -29,7 +29,7 @@ void ComboBoxLineEdit::resizeEvent(QResizeEvent *)
(rect().bottom() + 1 - sz.height())/2); (rect().bottom() + 1 - sz.height())/2);
} }
void ComboBoxLineEdit::updateClearButton(const QString& text) void ContentSelectorView::ComboBoxLineEdit::updateClearButton(const QString& text)
{ {
mClearButton->setVisible(!text.isEmpty()); mClearButton->setVisible(!text.isEmpty());
} }

View file

@ -14,22 +14,24 @@
class QToolButton; class QToolButton;
class ComboBoxLineEdit : public QLineEdit namespace ContentSelectorView
{ {
Q_OBJECT class ComboBoxLineEdit : public QLineEdit
{
Q_OBJECT
public: public:
ComboBoxLineEdit(QWidget *parent = 0); ComboBoxLineEdit(QWidget *parent = 0);
protected: protected:
void resizeEvent(QResizeEvent *); void resizeEvent(QResizeEvent *);
private slots: private slots:
void updateClearButton(const QString &text); void updateClearButton(const QString &text);
private:
QToolButton *mClearButton;
};
private:
QToolButton *mClearButton;
};
}
#endif // LIENEDIT_H #endif // LIENEDIT_H

View file

@ -0,0 +1,137 @@
#include "contentselector.hpp"
#include "../model/contentmodel.hpp"
#include "../model/esmfile.hpp"
#include <QSortFilterProxyModel>
#include <QDebug>
#include <QMenu>
#include <QContextMenuEvent>
ContentSelectorView::ContentSelector::ContentSelector(QWidget *parent) :
QDialog(parent)
{
setupUi(this);
buildContentModel();
buildGameFileView();
buildAddonView();
buildProfilesView();
updateViews();
}
void ContentSelectorView::ContentSelector::buildContentModel()
{
mContentModel = new ContentSelectorModel::ContentModel();
connect(mContentModel, SIGNAL(layoutChanged()), this, SLOT(updateViews()));
}
void ContentSelectorView::ContentSelector::buildGameFileView()
{
mGameFileProxyModel = new QSortFilterProxyModel(this);
mGameFileProxyModel->setFilterRegExp(QString::number((int)ContentSelectorModel::ContentType_GameFile));
mGameFileProxyModel->setFilterRole (Qt::UserRole);
mGameFileProxyModel->setSourceModel (mContentModel);
gameFileView->setPlaceholderText(QString("Select a game file..."));
gameFileView->setModel(mGameFileProxyModel);
connect(gameFileView, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentGameFileIndexChanged(int)));
connect(gameFileView, SIGNAL(currentIndexChanged(int)), this, SIGNAL(signalGameFileChanged(int)));
gameFileView->setCurrentIndex(-1);
gameFileView->setCurrentIndex(0);
}
void ContentSelectorView::ContentSelector::buildAddonView()
{
mAddonProxyModel = new QSortFilterProxyModel(this);
mAddonProxyModel->setFilterRegExp (QString::number((int)ContentSelectorModel::ContentType_Addon));
mAddonProxyModel->setFilterRole (Qt::UserRole);
mAddonProxyModel->setDynamicSortFilter (true);
mAddonProxyModel->setSourceModel (mContentModel);
addonView->setModel(mAddonProxyModel);
connect(addonView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotAddonTableItemClicked(const QModelIndex &)));
}
void ContentSelectorView::ContentSelector::buildProfilesView()
{
profilesComboBox->setPlaceholderText(QString("Select a profile..."));
connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentProfileIndexChanged(int)));
}
void ContentSelectorView::ContentSelector::updateViews()
{
// Ensure the columns are hidden because sort() re-enables them
addonView->setColumnHidden(1, true);
addonView->setColumnHidden(2, true);
addonView->setColumnHidden(3, true);
addonView->setColumnHidden(4, true);
addonView->setColumnHidden(5, true);
addonView->setColumnHidden(6, true);
addonView->setColumnHidden(7, true);
addonView->setColumnHidden(8, true);
addonView->resizeColumnsToContents();
}
void ContentSelectorView::ContentSelector::addFiles(const QString &path)
{
mContentModel->addFiles(path);
//mContentModel->sort(3); // Sort by date accessed
gameFileView->setCurrentIndex(-1);
mContentModel->uncheckAll();
}
QStringList ContentSelectorView::ContentSelector::checkedItemsPaths()
{
QStringList itemPaths;
foreach( const ContentSelectorModel::EsmFile *file, mContentModel->checkedItems())
itemPaths << file->path();
return itemPaths;
}
void ContentSelectorView::ContentSelector::slotCurrentProfileIndexChanged(int index)
{
emit profileChanged(index);
}
void ContentSelectorView::ContentSelector::slotCurrentGameFileIndexChanged(int index)
{
static int oldIndex = -1;
QAbstractItemModel *const model = gameFileView->model();
QSortFilterProxyModel *proxy = dynamic_cast<QSortFilterProxyModel *>(model);
if (proxy)
proxy->setDynamicSortFilter(false);
if (oldIndex > -1)
model->setData(model->index(oldIndex, 0), false, Qt::UserRole + 1);
oldIndex = index;
model->setData(model->index(index, 0), true, Qt::UserRole + 1);
if (proxy)
proxy->setDynamicSortFilter(true);
emit signalGameFileChanged(true);
}
void ContentSelectorView::ContentSelector::slotAddonTableItemClicked(const QModelIndex &index)
{
QAbstractItemModel *const model = addonView->model();
//QSortFilterProxyModel *proxy = dynamic_cast<QSortFilterProxyModel *>(model);
if (model->data(index, Qt::CheckStateRole).toInt() == Qt::Unchecked)
model->setData(index, Qt::Checked, Qt::CheckStateRole);
else
model->setData(index, Qt::Unchecked, Qt::CheckStateRole);
}

View file

@ -0,0 +1,53 @@
#ifndef CONTENTSELECTOR_HPP
#define CONTENTSELECTOR_HPP
#include <QDialog>
#include "ui_datafilespage.h"
namespace ContentSelectorModel { class ContentModel; }
class QSortFilterProxyModel;
namespace ContentSelectorView
{
class ContentSelector : public QDialog, protected Ui::DataFilesPage
{
Q_OBJECT
protected:
ContentSelectorModel::ContentModel *mContentModel;
QSortFilterProxyModel *mGameFileProxyModel;
QSortFilterProxyModel *mAddonProxyModel;
public:
explicit ContentSelector(QWidget *parent = 0);
static ContentSelector &cast(QWidget *subject); //static constructor function for singleton performance.
void addFiles(const QString &path);
void setCheckState(QModelIndex index, QSortFilterProxyModel *model);
QStringList checkedItemsPaths();
private:
void buildContentModel();
void buildGameFileView();
void buildAddonView();
void buildProfilesView();
signals:
void profileChanged(int index);
void signalGameFileChanged(int value);
private slots:
void updateViews();
void slotCurrentProfileIndexChanged(int index);
void slotCurrentGameFileIndexChanged(int index);
void slotAddonTableItemClicked(const QModelIndex &index);
};
}
#endif // CONTENTSELECTOR_HPP

View file

@ -1,9 +1,10 @@
#include <QToolButton> #include <QToolButton>
#include <QStyle> #include <QStyle>
#include <QStylePainter>
#include "lineedit.hpp" #include "lineedit.hpp"
LineEdit::LineEdit(QWidget *parent) ContentSelectorView::LineEdit::LineEdit(QWidget *parent)
: QLineEdit(parent) : QLineEdit(parent)
{ {
mClearButton = new QToolButton(this); mClearButton = new QToolButton(this);
@ -24,7 +25,7 @@ LineEdit::LineEdit(QWidget *parent)
qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2)); qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2));
} }
void LineEdit::resizeEvent(QResizeEvent *) void ContentSelectorView::LineEdit::resizeEvent(QResizeEvent *)
{ {
QSize sz = mClearButton->sizeHint(); QSize sz = mClearButton->sizeHint();
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
@ -32,7 +33,7 @@ void LineEdit::resizeEvent(QResizeEvent *)
(rect().bottom() + 1 - sz.height())/2); (rect().bottom() + 1 - sz.height())/2);
} }
void LineEdit::updateClearButton(const QString& text) void ContentSelectorView::LineEdit::updateClearButton(const QString& text)
{ {
mClearButton->setVisible(!text.isEmpty()); mClearButton->setVisible(!text.isEmpty());
} }

View file

@ -14,22 +14,26 @@
class QToolButton; class QToolButton;
class LineEdit : public QLineEdit namespace ContentSelectorView
{ {
Q_OBJECT class LineEdit : public QLineEdit
{
Q_OBJECT
public: QString mPlaceholderText;
LineEdit(QWidget *parent = 0);
protected: public:
void resizeEvent(QResizeEvent *); LineEdit(QWidget *parent = 0);
private slots: protected:
void updateClearButton(const QString &text); void resizeEvent(QResizeEvent *);
private: private slots:
QToolButton *mClearButton; void updateClearButton(const QString &text);
};
private:
QToolButton *mClearButton;
};
}
#endif // LIENEDIT_H #endif // LIENEDIT_H

View file

@ -7,7 +7,7 @@
#include "profilescombobox.hpp" #include "profilescombobox.hpp"
#include "comboboxlineedit.hpp" #include "comboboxlineedit.hpp"
ProfilesComboBox::ProfilesComboBox(QWidget *parent) : ContentSelectorView::ProfilesComboBox::ProfilesComboBox(QWidget *parent) :
QComboBox(parent) QComboBox(parent)
{ {
mValidator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore mValidator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore
@ -21,7 +21,7 @@ ProfilesComboBox::ProfilesComboBox(QWidget *parent) :
setInsertPolicy(QComboBox::NoInsert); setInsertPolicy(QComboBox::NoInsert);
} }
void ProfilesComboBox::setEditEnabled(bool editable) void ContentSelectorView::ProfilesComboBox::setEditEnabled(bool editable)
{ {
if (isEditable() == editable) if (isEditable() == editable)
return; return;
@ -47,7 +47,7 @@ void ProfilesComboBox::setEditEnabled(bool editable)
SLOT(slotTextChanged(QString))); SLOT(slotTextChanged(QString)));
} }
void ProfilesComboBox::slotTextChanged(const QString &text) void ContentSelectorView::ProfilesComboBox::slotTextChanged(const QString &text)
{ {
QPalette *palette = new QPalette(); QPalette *palette = new QPalette();
palette->setColor(QPalette::Text,Qt::red); palette->setColor(QPalette::Text,Qt::red);
@ -61,7 +61,7 @@ void ProfilesComboBox::slotTextChanged(const QString &text)
} }
} }
void ProfilesComboBox::slotEditingFinished() void ContentSelectorView::ProfilesComboBox::slotEditingFinished()
{ {
QString current = currentText(); QString current = currentText();
QString previous = itemText(currentIndex()); QString previous = itemText(currentIndex());
@ -82,7 +82,7 @@ void ProfilesComboBox::slotEditingFinished()
emit(profileRenamed(previous, current)); emit(profileRenamed(previous, current));
} }
void ProfilesComboBox::slotIndexChanged(int index) void ContentSelectorView::ProfilesComboBox::slotIndexChanged(int index)
{ {
if (index == -1) if (index == -1)
return; return;
@ -90,3 +90,24 @@ void ProfilesComboBox::slotIndexChanged(int index)
emit(profileChanged(mOldProfile, currentText())); emit(profileChanged(mOldProfile, currentText()));
mOldProfile = itemText(index); mOldProfile = itemText(index);
} }
void ContentSelectorView::ProfilesComboBox::paintEvent(QPaintEvent *)
{
QStylePainter painter(this);
painter.setPen(palette().color(QPalette::Text));
// draw the combobox frame, focusrect and selected etc.
QStyleOptionComboBox opt;
initStyleOption(&opt);
painter.drawComplexControl(QStyle::CC_ComboBox, opt);
// draw the icon and text
if (!opt.editable && currentIndex() == -1) // <<< we adjust the text displayed when nothing is selected
opt.currentText = mPlaceholderText;
painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
}
void ContentSelectorView::ProfilesComboBox::setPlaceholderText(const QString &text)
{
mPlaceholderText = text;
}

View file

@ -0,0 +1,38 @@
#ifndef PROFILESCOMBOBOX_HPP
#define PROFILESCOMBOBOX_HPP
#include <QComboBox>
#include <QStylePainter>
class QString;
class QRegExpValidator;
namespace ContentSelectorView
{
class ProfilesComboBox : public QComboBox
{
Q_OBJECT
public:
explicit ProfilesComboBox(QWidget *parent = 0);
void setEditEnabled(bool editable);
void setPlaceholderText (const QString &text);
signals:
void profileChanged(const QString &previous, const QString &current);
void profileRenamed(const QString &oldName, const QString &newName);
private slots:
void slotEditingFinished();
void slotIndexChanged(int index);
void slotTextChanged(const QString &text);
private:
QString mOldProfile;
QString mPlaceholderText;
QRegExpValidator *mValidator;
protected:
void paintEvent(QPaintEvent *);
};
}
#endif // PROFILESCOMBOBOX_HPP

View file

@ -34,7 +34,7 @@ public:
float getFVer() const { if(mHeader.mData.version == VER_12) return 1.2; else return 1.3; } float getFVer() const { if(mHeader.mData.version == VER_12) return 1.2; else return 1.3; }
const std::string getAuthor() const { return mHeader.mData.author.toString(); } const std::string getAuthor() const { return mHeader.mData.author.toString(); }
const std::string getDesc() const { return mHeader.mData.desc.toString(); } const std::string getDesc() const { return mHeader.mData.desc.toString(); }
const std::vector<Header::MasterData> &getMasters() const { return mHeader.mMaster; } const std::vector<Header::MasterData> &getGameFiles() const { return mHeader.mMaster; }
int getFormat() const; int getFormat() const;
const NAME &retSubName() const { return mCtx.subName; } const NAME &retSubName() const { return mCtx.subName; }
uint32_t getSubSize() const { return mCtx.leftSub; } uint32_t getSubSize() const { return mCtx.leftSub; }

View file

@ -172,7 +172,7 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
// If the most significant 8 bits are used, then this reference already exists. // If the most significant 8 bits are used, then this reference already exists.
// In this case, do not spawn a new reference, but overwrite the old one. // In this case, do not spawn a new reference, but overwrite the old one.
ref.mRefnum &= 0x00ffffff; // delete old plugin ID ref.mRefnum &= 0x00ffffff; // delete old plugin ID
const std::vector<Header::MasterData> &masters = esm.getMasters(); const std::vector<Header::MasterData> &masters = esm.getGameFiles();
global = masters[local-1].index + 1; global = masters[local-1].index + 1;
ref.mRefnum |= global << 24; // insert global plugin ID ref.mRefnum |= global << 24; // insert global plugin ID
} }
@ -276,7 +276,7 @@ bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
int local = (mref.mRefnum & 0xff000000) >> 24; int local = (mref.mRefnum & 0xff000000) >> 24;
size_t global = esm.getIndex() + 1; size_t global = esm.getIndex() + 1;
mref.mRefnum &= 0x00ffffff; // delete old plugin ID mref.mRefnum &= 0x00ffffff; // delete old plugin ID
const std::vector<Header::MasterData> &masters = esm.getMasters(); const std::vector<Header::MasterData> &masters = esm.getGameFiles();
global = masters[local-1].index + 1; global = masters[local-1].index + 1;
mref.mRefnum |= global << 24; // insert global plugin ID mref.mRefnum |= global << 24; // insert global plugin ID

View file

@ -1,445 +0,0 @@
#include <QTextDecoder>
#include <QTextCodec>
#include <QFileInfo>
#include <QDir>
#include <stdexcept>
#include <components/esm/esmreader.hpp>
#include "esm/esmfile.hpp"
#include "datafilesmodel.hpp"
#include <QDebug>
DataFilesModel::DataFilesModel(QObject *parent) :
QAbstractTableModel(parent)
{
mEncoding = QString("win1252");
}
DataFilesModel::~DataFilesModel()
{
}
void DataFilesModel::setEncoding(const QString &encoding)
{
mEncoding = encoding;
}
void DataFilesModel::setCheckState(const QModelIndex &index, Qt::CheckState state)
{
setData(index, state, Qt::CheckStateRole);
}
Qt::CheckState DataFilesModel::checkState(const QModelIndex &index)
{
EsmFile *file = item(index.row());
return mCheckStates[file->fileName()];
}
int DataFilesModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 9;
}
int DataFilesModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : mFiles.count();
}
bool DataFilesModel::moveRow(int oldrow, int row, const QModelIndex &parent)
{
if (oldrow < 0 || row < 0 || oldrow == row)
return false;
emit layoutAboutToBeChanged();
//emit beginMoveRows(parent, oldrow, oldrow, parent, row);
mFiles.swap(oldrow, row);
//emit endInsertRows();
emit layoutChanged();
return true;
}
QVariant DataFilesModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
EsmFile *file = item(index.row());
if (!file)
return QVariant();
const int column = index.column();
switch (role) {
case Qt::DisplayRole: {
switch (column) {
case 0:
return file->fileName();
case 1:
return file->author();
case 2:
return QString("%1 kB").arg(int((file->size() + 1023) / 1024));
case 3:
//return file->modified().toString(Qt::TextDate);
return file->modified().toString(Qt::ISODate);
case 4:
return file->accessed().toString(Qt::TextDate);
case 5:
return file->version();
case 6:
return file->path();
case 7:
return file->masters().join(", ");
case 8:
return file->description();
}
}
case Qt::TextAlignmentRole: {
switch (column) {
case 0:
case 1:
return Qt::AlignLeft + Qt::AlignVCenter;
case 2:
case 3:
case 4:
case 5:
return Qt::AlignRight + Qt::AlignVCenter;
default:
return Qt::AlignLeft + Qt::AlignVCenter;
}
}
case Qt::CheckStateRole: {
if (column != 0)
return QVariant();
return mCheckStates[file->fileName()];
}
case Qt::ToolTipRole:
{
if (column != 0)
return QVariant();
if (file->version() == 0.0f)
return QVariant(); // Data not set
QString tooltip =
QString("<b>Author:</b> %1<br/> \
<b>Version:</b> %2<br/> \
<br/><b>Description:</b><br/>%3<br/> \
<br/><b>Dependencies: </b>%4<br/>")
.arg(file->author())
.arg(QString::number(file->version()))
.arg(file->description())
.arg(file->masters().join(", "));
return tooltip;
}
default:
return QVariant();
}
}
Qt::ItemFlags DataFilesModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
EsmFile *file = item(index.row());
if (!file)
return Qt::NoItemFlags;
if (canBeChecked(file)) {
if (index.column() == 0) {
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
} else {
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
} else {
if (index.column() == 0) {
return Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
} else {
return Qt::NoItemFlags | Qt::ItemIsSelectable;
}
}
}
QVariant DataFilesModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (section) {
case 0: return tr("Name");
case 1: return tr("Author");
case 2: return tr("Size");
case 3: return tr("Modified");
case 4: return tr("Accessed");
case 5: return tr("Version");
case 6: return tr("Path");
case 7: return tr("Masters");
case 8: return tr("Description");
}
} else {
// Show row numbers
return ++section;
}
return QVariant();
}
bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;
if (role == Qt::CheckStateRole) {
QString name = item(index.row())->fileName();
mCheckStates[name] = static_cast<Qt::CheckState>(value.toInt());
// Force a redraw of the view since unchecking one item can affect another
QModelIndex firstIndex = indexFromItem(mFiles.first());
QModelIndex lastIndex = indexFromItem(mFiles.last());
emit dataChanged(firstIndex, lastIndex);
emit checkedItemsChanged(checkedItems());
return true;
}
return false;
}
bool lessThanEsmFile(const EsmFile *e1, const EsmFile *e2)
{
//Masters first then alphabetically
if (e1->fileName().endsWith(".esm") && !e2->fileName().endsWith(".esm"))
return true;
if (!e1->fileName().endsWith(".esm") && e2->fileName().endsWith(".esm"))
return false;
return e1->fileName().toLower() < e2->fileName().toLower();
}
bool lessThanDate(const EsmFile *e1, const EsmFile *e2)
{
if (e1->modified().toString(Qt::ISODate) < e2->modified().toString(Qt::ISODate)) {
return true;
} else {
return false;
}
}
void DataFilesModel::sort(int column, Qt::SortOrder order)
{
emit layoutAboutToBeChanged();
if (column == 3) {
qSort(mFiles.begin(), mFiles.end(), lessThanDate);
} else {
qSort(mFiles.begin(), mFiles.end(), lessThanEsmFile);
}
emit layoutChanged();
}
void DataFilesModel::addFile(EsmFile *file)
{
emit beginInsertRows(QModelIndex(), mFiles.count(), mFiles.count());
mFiles.append(file);
emit endInsertRows();
}
void DataFilesModel::addFiles(const QString &path)
{
QDir dir(path);
QStringList filters;
filters << "*.esp" << "*.esm";
dir.setNameFilters(filters);
// Create a decoder for non-latin characters in esx metadata
QTextCodec *codec;
if (mEncoding == QLatin1String("win1252")) {
codec = QTextCodec::codecForName("windows-1252");
} else if (mEncoding == QLatin1String("win1251")) {
codec = QTextCodec::codecForName("windows-1251");
} else if (mEncoding == QLatin1String("win1250")) {
codec = QTextCodec::codecForName("windows-1250");
} else {
return; // This should never happen;
}
QTextDecoder *decoder = codec->makeDecoder();
foreach (const QString &path, dir.entryList()) {
QFileInfo info(dir.absoluteFilePath(path));
EsmFile *file = new EsmFile(path);
try {
ESM::ESMReader fileReader;
ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding.toStdString()));
fileReader.setEncoder(&encoder);
fileReader.open(dir.absoluteFilePath(path).toStdString());
std::vector<ESM::Header::MasterData> mlist = fileReader.getMasters();
QStringList masters;
for (unsigned int i = 0; i < mlist.size(); ++i) {
QString master = QString::fromStdString(mlist[i].name);
masters.append(master);
}
file->setAuthor(decoder->toUnicode(fileReader.getAuthor().c_str()));
file->setSize(info.size());
file->setDates(info.lastModified(), info.lastRead());
file->setVersion(fileReader.getFVer());
file->setPath(info.absoluteFilePath());
file->setMasters(masters);
file->setDescription(decoder->toUnicode(fileReader.getDesc().c_str()));
// Put the file in the table
if (findItem(path) == 0)
addFile(file);
} catch(std::runtime_error &e) {
// An error occurred while reading the .esp
qWarning() << "Error reading esp: " << e.what();
continue;
}
}
delete decoder;
}
QModelIndex DataFilesModel::indexFromItem(EsmFile *item) const
{
if (item)
return createIndex(mFiles.indexOf(item), 0);
return QModelIndex();
}
EsmFile* DataFilesModel::findItem(const QString &name)
{
QList<EsmFile *>::ConstIterator it;
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
int i = 0;
for (it = mFiles.constBegin(); it != itEnd; ++it) {
EsmFile *file = item(i);
++i;
if (name == file->fileName())
return file;
}
// Not found
return 0;
}
EsmFile* DataFilesModel::item(int row) const
{
if (row >= 0 && row < mFiles.count())
return mFiles.at(row);
else
return 0;
}
QStringList DataFilesModel::checkedItems()
{
QStringList list;
QList<EsmFile *>::ConstIterator it;
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
int i = 0;
for (it = mFiles.constBegin(); it != itEnd; ++it) {
EsmFile *file = item(i);
++i;
QString name = file->fileName();
// Only add the items that are in the checked list and available
if (mCheckStates[name] == Qt::Checked && canBeChecked(file))
list << name;
}
return list;
}
QStringList DataFilesModel::checkedItemsPaths()
{
QStringList list;
QList<EsmFile *>::ConstIterator it;
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
int i = 0;
for (it = mFiles.constBegin(); it != itEnd; ++it) {
EsmFile *file = item(i);
++i;
if (mCheckStates[file->fileName()] == Qt::Checked && canBeChecked(file))
list << file->path();
}
return list;
}
void DataFilesModel::uncheckAll()
{
emit layoutAboutToBeChanged();
mCheckStates.clear();
emit layoutChanged();
}
QStringList DataFilesModel::uncheckedItems()
{
QStringList list;
QStringList checked = checkedItems();
QList<EsmFile *>::ConstIterator it;
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
int i = 0;
for (it = mFiles.constBegin(); it != itEnd; ++it) {
EsmFile *file = item(i);
++i;
// Add the items that are not in the checked list
if (!checked.contains(file->fileName()))
list << file->fileName();
}
return list;
}
bool DataFilesModel::canBeChecked(EsmFile *file) const
{
//element can be checked if all its dependencies are
bool canBeChecked = true;
foreach (const QString &master, file->masters())
{
if (!mCheckStates.contains(master) || mCheckStates[master] != Qt::Checked)
{
canBeChecked = false;
break;
}
}
return canBeChecked;
}

View file

@ -1,66 +0,0 @@
#ifndef DATAFILESMODEL_HPP
#define DATAFILESMODEL_HPP
#include <QAbstractTableModel>
#include <QStringList>
#include <QString>
#include <QHash>
class EsmFile;
class DataFilesModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit DataFilesModel(QObject *parent = 0);
virtual ~DataFilesModel();
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
bool moveRow(int oldrow, int row, const QModelIndex &parent = QModelIndex());
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
inline QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
{ return QAbstractTableModel::index(row, column, parent); }
void setEncoding(const QString &encoding);
void addFiles(const QString &path);
void uncheckAll();
QStringList checkedItems();
QStringList uncheckedItems();
QStringList checkedItemsPaths();
Qt::CheckState checkState(const QModelIndex &index);
void setCheckState(const QModelIndex &index, Qt::CheckState state);
QModelIndex indexFromItem(EsmFile *item) const;
EsmFile* findItem(const QString &name);
EsmFile* item(int row) const;
signals:
void checkedItemsChanged(const QStringList &items);
private:
bool canBeChecked(EsmFile *file) const;
void addFile(EsmFile *file);
QList<EsmFile *> mFiles;
QHash<QString, Qt::CheckState> mCheckStates;
QString mEncoding;
};
#endif // DATAFILESMODEL_HPP

View file

@ -1,50 +0,0 @@
#include "esmfile.hpp"
EsmFile::EsmFile(QString fileName, ModelItem *parent)
: ModelItem(parent)
{
mFileName = fileName;
mSize = 0;
mVersion = 0.0f;
}
void EsmFile::setFileName(const QString &fileName)
{
mFileName = fileName;
}
void EsmFile::setAuthor(const QString &author)
{
mAuthor = author;
}
void EsmFile::setSize(const int size)
{
mSize = size;
}
void EsmFile::setDates(const QDateTime &modified, const QDateTime &accessed)
{
mModified = modified;
mAccessed = accessed;
}
void EsmFile::setVersion(float version)
{
mVersion = version;
}
void EsmFile::setPath(const QString &path)
{
mPath = path;
}
void EsmFile::setMasters(const QStringList &masters)
{
mMasters = masters;
}
void EsmFile::setDescription(const QString &description)
{
mDescription = description;
}

View file

@ -1,54 +0,0 @@
#ifndef ESMFILE_HPP
#define ESMFILE_HPP
#include <QDateTime>
#include <QStringList>
#include "../modelitem.hpp"
class EsmFile : public ModelItem
{
Q_OBJECT
Q_PROPERTY(QString filename READ fileName)
public:
EsmFile(QString fileName = QString(), ModelItem *parent = 0);
~EsmFile()
{}
void setFileName(const QString &fileName);
void setAuthor(const QString &author);
void setSize(const int size);
void setDates(const QDateTime &modified, const QDateTime &accessed);
void setVersion(const float version);
void setPath(const QString &path);
void setMasters(const QStringList &masters);
void setDescription(const QString &description);
inline QString fileName() const { return mFileName; }
inline QString author() const { return mAuthor; }
inline int size() const { return mSize; }
inline QDateTime modified() const { return mModified; }
inline QDateTime accessed() const { return mAccessed; }
inline float version() const { return mVersion; }
inline QString path() const { return mPath; }
inline QStringList masters() const { return mMasters; }
inline QString description() const { return mDescription; }
private:
QString mFileName;
QString mAuthor;
int mSize;
QDateTime mModified;
QDateTime mAccessed;
float mVersion;
QString mPath;
QStringList mMasters;
QString mDescription;
};
#endif

View file

@ -1,57 +0,0 @@
#include "modelitem.hpp"
ModelItem::ModelItem(ModelItem *parent)
: mParentItem(parent)
, QObject(parent)
{
}
ModelItem::~ModelItem()
{
qDeleteAll(mChildItems);
}
ModelItem *ModelItem::parent()
{
return mParentItem;
}
int ModelItem::row() const
{
if (mParentItem)
return 1;
//return mParentItem->childRow(const_cast<ModelItem*>(this));
//return mParentItem->mChildItems.indexOf(const_cast<ModelItem*>(this));
return -1;
}
int ModelItem::childCount() const
{
return mChildItems.count();
}
int ModelItem::childRow(ModelItem *child) const
{
Q_ASSERT(child);
return mChildItems.indexOf(child);
}
ModelItem *ModelItem::child(int row)
{
return mChildItems.value(row);
}
void ModelItem::appendChild(ModelItem *item)
{
mChildItems.append(item);
}
void ModelItem::removeChild(int row)
{
mChildItems.removeAt(row);
}

View file

@ -1,32 +0,0 @@
#ifndef MODELITEM_HPP
#define MODELITEM_HPP
#include <QObject>
#include <QList>
class ModelItem : public QObject
{
Q_OBJECT
public:
ModelItem(ModelItem *parent = 0);
~ModelItem();
ModelItem *parent();
int row() const;
int childCount() const;
int childRow(ModelItem *child) const;
ModelItem *child(int row);
void appendChild(ModelItem *child);
void removeChild(int row);
//virtual bool acceptChild(ModelItem *child);
protected:
ModelItem *mParentItem;
QList<ModelItem*> mChildItems;
};
#endif

View file

@ -1,17 +0,0 @@
#include "pluginsproxymodel.hpp"
PluginsProxyModel::PluginsProxyModel(QObject *parent) :
QSortFilterProxyModel(parent)
{
}
PluginsProxyModel::~PluginsProxyModel()
{
}
QVariant PluginsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation != Qt::Vertical || role != Qt::DisplayRole)
return QSortFilterProxyModel::headerData(section, orientation, role);
return section + 1;
}

View file

@ -1,18 +0,0 @@
#ifndef PLUGINSPROXYMODEL_HPP
#define PLUGINSPROXYMODEL_HPP
#include <QSortFilterProxyModel>
class QVariant;
class PluginsProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit PluginsProxyModel(QObject *parent = 0);
~PluginsProxyModel();
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
};
#endif // PLUGINSPROXYMODEL_HPP

View file

@ -1,11 +0,0 @@
#ifndef NATURALSORT_H
#define NATURALSORT_H
#include <QString>
bool naturalSortLessThanCS( const QString &left, const QString &right );
bool naturalSortLessThanCI( const QString &left, const QString &right );
bool naturalSortGreaterThanCS( const QString &left, const QString &right );
bool naturalSortGreaterThanCI( const QString &left, const QString &right );
#endif

View file

@ -1,30 +0,0 @@
#ifndef PROFILESCOMBOBOX_HPP
#define PROFILESCOMBOBOX_HPP
#include <QComboBox>
class QString;
class QRegExpValidator;
class ProfilesComboBox : public QComboBox
{
Q_OBJECT
public:
explicit ProfilesComboBox(QWidget *parent = 0);
void setEditEnabled(bool editable);
signals:
void profileChanged(const QString &previous, const QString &current);
void profileRenamed(const QString &oldName, const QString &newName);
private slots:
void slotEditingFinished();
void slotIndexChanged(int index);
void slotTextChanged(const QString &text);
private:
QString mOldProfile;
QRegExpValidator *mValidator;
};
#endif // PROFILESCOMBOBOX_HPP

View file

@ -47,6 +47,7 @@ Marc Bouvier (CramitDeFrog)
Marcin Hulist (Gohan) Marcin Hulist (Gohan)
Mark Siewert (mark76) Mark Siewert (mark76)
Mateusz Kołaczek (PL_kolek) Mateusz Kołaczek (PL_kolek)
Michael Hogan (Xethik)
Michael Mc Donnell Michael Mc Donnell
Michael Papageorgiou (werdanith) Michael Papageorgiou (werdanith)
Michał Bień (Glorf) Michał Bień (Glorf)

View file

@ -7,107 +7,260 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>518</width> <width>518</width>
<height>304</height> <height>313</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QHBoxLayout" name="filterLayout"> <widget class="QGroupBox" name="contentGroupBox">
<item> <property name="title">
<spacer name="horizontalSpacer"> <string>Content</string>
<property name="orientation"> </property>
<enum>Qt::Horizontal</enum> <layout class="QVBoxLayout" name="verticalLayout_2">
</property> <item>
<property name="sizeHint" stdset="0"> <layout class="QHBoxLayout" name="filterLayout">
<size> <item>
<width>40</width> <widget class="ContentSelectorView::ProfilesComboBox" name="gameFileView">
<height>20</height> <property name="editable">
</size> <bool>false</bool>
</property> </property>
</spacer> </widget>
</item> </item>
<item> </layout>
<widget class="QLabel" name="filterLabel"> </item>
<property name="text"> <item>
<string>Filter:</string> <layout class="QHBoxLayout" name="horizontalLayout_3">
</property> <item>
</widget> <widget class="QTableView" name="addonView">
</item> <property name="sizePolicy">
<item> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<widget class="LineEdit" name="filterLineEdit"/> <horstretch>0</horstretch>
</item> <verstretch>0</verstretch>
</layout> </sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropOverwriteMode">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideLeft</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</item>
</layout>
<zorder></zorder>
<zorder></zorder>
</widget>
</item> </item>
<item> <item>
<widget class="QSplitter" name="splitter"> <widget class="QGroupBox" name="projectGroupBox">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="orientation"> <property name="title">
<enum>Qt::Horizontal</enum> <string>Project</string>
</property> </property>
<property name="childrenCollapsible"> <property name="alignment">
<bool>false</bool> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
<widget class="QTableView" name="mastersTable"/> <layout class="QHBoxLayout" name="horizontalLayout">
<widget class="QTableView" name="pluginsTable"/> <item>
<widget class="QFrame" name="fileWidgetFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="projectButtonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Open</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="projectCreateButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <widget class="QFrame" name="adjusterWidgetFrame">
<item> <property name="sizePolicy">
<widget class="QLabel" name="profileLabel"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<property name="text"> <horstretch>1</horstretch>
<string>Current Profile:</string> <verstretch>0</verstretch>
</property> </sizepolicy>
</widget> </property>
</item> <property name="frameShape">
<item> <enum>QFrame::NoFrame</enum>
<widget class="ProfilesComboBox" name="profilesComboBox"> </property>
<property name="enabled"> <property name="frameShadow">
<bool>true</bool> <enum>QFrame::Plain</enum>
</property> </property>
<property name="sizePolicy"> <property name="lineWidth">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <number>0</number>
<horstretch>0</horstretch> </property>
<verstretch>0</verstretch> <layout class="QHBoxLayout" name="horizontalLayout_4">
</sizepolicy> <property name="spacing">
</property> <number>0</number>
</widget> </property>
</item> <property name="margin">
<item> <number>0</number>
<widget class="QToolButton" name="newProfileButton"> </property>
<property name="toolTip"> </layout>
<string>New Profile</string> </widget>
</property> </item>
<property name="text"> <item>
<string>&amp;New Profile</string> <widget class="QGroupBox" name="profileGroupBox">
</property> <property name="focusPolicy">
<property name="autoRaise"> <enum>Qt::NoFocus</enum>
<bool>true</bool> </property>
</property> <property name="title">
</widget> <string>Profile</string>
</item> </property>
<item> <property name="flat">
<widget class="QToolButton" name="deleteProfileButton"> <bool>false</bool>
<property name="toolTip"> </property>
<string>Delete Profile</string> <layout class="QHBoxLayout" name="horizontalLayout_2">
</property> <property name="spacing">
<property name="text"> <number>6</number>
<string>Delete Profile</string> </property>
</property> <property name="leftMargin">
<property name="shortcut"> <number>3</number>
<string>Ctrl+D</string> </property>
</property> <property name="topMargin">
<property name="autoRaise"> <number>9</number>
<bool>true</bool> </property>
</property> <property name="rightMargin">
</widget> <number>0</number>
</item> </property>
</layout> <property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="ContentSelectorView::ProfilesComboBox" name="profilesComboBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="newProfileButton">
<property name="toolTip">
<string>New Profile</string>
</property>
<property name="text">
<string>&amp;New Profile</string>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="deleteProfileButton">
<property name="toolTip">
<string>Delete Profile</string>
</property>
<property name="text">
<string>Delete Profile</string>
</property>
<property name="shortcut">
<string>Ctrl+D</string>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item> </item>
</layout> </layout>
<action name="newProfileAction"> <action name="newProfileAction">
@ -140,6 +293,9 @@
</property> </property>
</action> </action>
<action name="checkAction"> <action name="checkAction">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text"> <property name="text">
<string>Check Selection</string> <string>Check Selection</string>
</property> </property>
@ -152,14 +308,9 @@
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
<class>LineEdit</class> <class>ContentSelectorView::ProfilesComboBox</class>
<extends>QLineEdit</extends>
<header location="global">components/fileorderlist/utils/lineedit.hpp</header>
</customwidget>
<customwidget>
<class>ProfilesComboBox</class>
<extends>QComboBox</extends> <extends>QComboBox</extends>
<header location="global">components/fileorderlist/utils/profilescombobox.hpp</header> <header>components/contentselector/view/profilescombobox.hpp</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>