mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-03 23:56:43 +00:00 
			
		
		
		
	Merge branch 'gmst' into next
This commit is contained in:
		
						commit
						2d937cd9e2
					
				
					 48 changed files with 1019 additions and 455 deletions
				
			
		| 
						 | 
				
			
			@ -1,17 +1,9 @@
 | 
			
		|||
set(LAUNCHER
 | 
			
		||||
    datafilespage.cpp
 | 
			
		||||
    graphicspage.cpp
 | 
			
		||||
    main.cpp
 | 
			
		||||
    maindialog.cpp
 | 
			
		||||
    playpage.cpp
 | 
			
		||||
 | 
			
		||||
    model/datafilesmodel.cpp
 | 
			
		||||
    model/modelitem.cpp
 | 
			
		||||
    model/esm/esmfile.cpp
 | 
			
		||||
 | 
			
		||||
    utils/filedialog.cpp
 | 
			
		||||
    utils/naturalsort.cpp
 | 
			
		||||
    utils/lineedit.cpp
 | 
			
		||||
    datafilespage.cpp
 | 
			
		||||
    utils/profilescombobox.cpp
 | 
			
		||||
    utils/textinputdialog.cpp
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,36 +11,20 @@ set(LAUNCHER
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
set(LAUNCHER_HEADER
 | 
			
		||||
    datafilespage.hpp
 | 
			
		||||
    graphicspage.hpp
 | 
			
		||||
    maindialog.hpp
 | 
			
		||||
    playpage.hpp
 | 
			
		||||
 | 
			
		||||
    model/datafilesmodel.hpp
 | 
			
		||||
    model/modelitem.hpp
 | 
			
		||||
    model/esm/esmfile.hpp
 | 
			
		||||
 | 
			
		||||
    utils/lineedit.hpp
 | 
			
		||||
    utils/filedialog.hpp
 | 
			
		||||
    utils/naturalsort.hpp
 | 
			
		||||
    datafilespage.hpp
 | 
			
		||||
    utils/profilescombobox.hpp
 | 
			
		||||
    utils/textinputdialog.hpp
 | 
			
		||||
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Headers that must be pre-processed
 | 
			
		||||
set(LAUNCHER_HEADER_MOC
 | 
			
		||||
    datafilespage.hpp
 | 
			
		||||
    graphicspage.hpp
 | 
			
		||||
    maindialog.hpp
 | 
			
		||||
    playpage.hpp
 | 
			
		||||
 | 
			
		||||
    model/datafilesmodel.hpp
 | 
			
		||||
    model/modelitem.hpp
 | 
			
		||||
    model/esm/esmfile.hpp
 | 
			
		||||
 | 
			
		||||
    utils/lineedit.hpp
 | 
			
		||||
    utils/filedialog.hpp
 | 
			
		||||
    datafilespage.hpp
 | 
			
		||||
    utils/profilescombobox.hpp
 | 
			
		||||
    utils/textinputdialog.hpp
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,14 +2,17 @@
 | 
			
		|||
 | 
			
		||||
#include <components/esm/esmreader.hpp>
 | 
			
		||||
#include <components/files/configurationmanager.hpp>
 | 
			
		||||
#include <components/fileorderlist/datafileslist.hpp>
 | 
			
		||||
#include <components/fileorderlist/utils/lineedit.hpp>
 | 
			
		||||
#include <components/fileorderlist/utils/naturalsort.hpp>
 | 
			
		||||
#include <components/fileorderlist/utils/filedialog.hpp>
 | 
			
		||||
 | 
			
		||||
#include "model/datafilesmodel.hpp"
 | 
			
		||||
#include "model/esm/esmfile.hpp"
 | 
			
		||||
////#include "model/datafilesmodel.hpp"
 | 
			
		||||
////#include "model/esm/esmfile.hpp"
 | 
			
		||||
 | 
			
		||||
#include "utils/profilescombobox.hpp"
 | 
			
		||||
#include "utils/filedialog.hpp"
 | 
			
		||||
#include "utils/lineedit.hpp"
 | 
			
		||||
#include "utils/naturalsort.hpp"
 | 
			
		||||
////#include "utils/filedialog.hpp"
 | 
			
		||||
////#include "utils/naturalsort.hpp"
 | 
			
		||||
#include "utils/textinputdialog.hpp"
 | 
			
		||||
 | 
			
		||||
#include "datafilespage.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -34,108 +37,11 @@ namespace boost
 | 
			
		|||
using namespace ESM;
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
//sort QModelIndexList ascending
 | 
			
		||||
bool rowGreaterThan(const QModelIndex &index1, const QModelIndex &index2)
 | 
			
		||||
{
 | 
			
		||||
    return index1.row() >= index2.row();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//sort QModelIndexList descending
 | 
			
		||||
bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2)
 | 
			
		||||
{
 | 
			
		||||
    return index1.row() <= index2.row();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent)
 | 
			
		||||
    : QWidget(parent)
 | 
			
		||||
    , mCfgMgr(cfg)
 | 
			
		||||
{
 | 
			
		||||
    // Models
 | 
			
		||||
    mMastersModel = new DataFilesModel(this);
 | 
			
		||||
    mPluginsModel = new DataFilesModel(this);
 | 
			
		||||
 | 
			
		||||
    mPluginsProxyModel = new QSortFilterProxyModel();
 | 
			
		||||
    mPluginsProxyModel->setDynamicSortFilter(true);
 | 
			
		||||
    mPluginsProxyModel->setSourceModel(mPluginsModel);
 | 
			
		||||
 | 
			
		||||
    // Filter toolbar
 | 
			
		||||
    QLabel *filterLabel = new QLabel(tr("&Filter:"), this);
 | 
			
		||||
    LineEdit *filterLineEdit = new LineEdit(this);
 | 
			
		||||
    filterLabel->setBuddy(filterLineEdit);
 | 
			
		||||
 | 
			
		||||
    QToolBar *filterToolBar = new QToolBar(this);
 | 
			
		||||
    filterToolBar->setMovable(false);
 | 
			
		||||
 | 
			
		||||
    // Create a container widget and a layout to get the spacer to work
 | 
			
		||||
    QWidget *filterWidget = new QWidget(this);
 | 
			
		||||
    QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget);
 | 
			
		||||
    QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
 | 
			
		||||
 | 
			
		||||
    filterLayout->addItem(hSpacer1);
 | 
			
		||||
    filterLayout->addWidget(filterLabel);
 | 
			
		||||
    filterLayout->addWidget(filterLineEdit);
 | 
			
		||||
 | 
			
		||||
    filterToolBar->addWidget(filterWidget);
 | 
			
		||||
 | 
			
		||||
    QCheckBox checkBox;
 | 
			
		||||
    unsigned int height = checkBox.sizeHint().height() + 4;
 | 
			
		||||
 | 
			
		||||
    mMastersTable = new QTableView(this);
 | 
			
		||||
    mMastersTable->setModel(mMastersModel);
 | 
			
		||||
    mMastersTable->setObjectName("MastersTable");
 | 
			
		||||
    mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
 | 
			
		||||
    mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection);
 | 
			
		||||
    mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
 | 
			
		||||
    mMastersTable->setAlternatingRowColors(true);
 | 
			
		||||
    mMastersTable->horizontalHeader()->setStretchLastSection(true);
 | 
			
		||||
    mMastersTable->horizontalHeader()->hide();
 | 
			
		||||
 | 
			
		||||
    // Set the row height to the size of the checkboxes
 | 
			
		||||
    mMastersTable->verticalHeader()->setDefaultSectionSize(height);
 | 
			
		||||
    mMastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
 | 
			
		||||
    mMastersTable->verticalHeader()->hide();
 | 
			
		||||
    mMastersTable->setColumnHidden(1, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(2, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(3, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(4, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(5, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(6, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(7, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(8, true);
 | 
			
		||||
 | 
			
		||||
    mPluginsTable = new QTableView(this);
 | 
			
		||||
    mPluginsTable->setModel(mPluginsProxyModel);
 | 
			
		||||
    mPluginsTable->setObjectName("PluginsTable");
 | 
			
		||||
    mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
 | 
			
		||||
    mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
 | 
			
		||||
    mPluginsTable->setSelectionMode(QAbstractItemView::SingleSelection);
 | 
			
		||||
    mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
 | 
			
		||||
    mPluginsTable->setAlternatingRowColors(true);
 | 
			
		||||
    mPluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
 | 
			
		||||
    mPluginsTable->horizontalHeader()->setStretchLastSection(true);
 | 
			
		||||
    mPluginsTable->horizontalHeader()->hide();
 | 
			
		||||
 | 
			
		||||
    mPluginsTable->verticalHeader()->setDefaultSectionSize(height);
 | 
			
		||||
    mPluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
 | 
			
		||||
    mPluginsTable->setColumnHidden(1, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(2, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(3, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(4, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(5, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(6, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(7, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(8, true);
 | 
			
		||||
 | 
			
		||||
    // Add both tables to a splitter
 | 
			
		||||
    QSplitter *splitter = new QSplitter(this);
 | 
			
		||||
    splitter->setOrientation(Qt::Horizontal);
 | 
			
		||||
    splitter->addWidget(mMastersTable);
 | 
			
		||||
    splitter->addWidget(mPluginsTable);
 | 
			
		||||
 | 
			
		||||
    // Adjust the default widget widths inside the splitter
 | 
			
		||||
    QList<int> sizeList;
 | 
			
		||||
    sizeList << 175 << 200;
 | 
			
		||||
    splitter->setSizes(sizeList);
 | 
			
		||||
    mDataFilesList = new DataFilesList(mCfgMgr, this);
 | 
			
		||||
 | 
			
		||||
    // Bottom part with profile options
 | 
			
		||||
    QLabel *profileLabel = new QLabel(tr("Current Profile: "), this);
 | 
			
		||||
| 
						 | 
				
			
			@ -155,8 +61,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent)
 | 
			
		|||
 | 
			
		||||
    QVBoxLayout *pageLayout = new QVBoxLayout(this);
 | 
			
		||||
 | 
			
		||||
    pageLayout->addWidget(filterToolBar);
 | 
			
		||||
    pageLayout->addWidget(splitter);
 | 
			
		||||
    pageLayout->addWidget(mDataFilesList);
 | 
			
		||||
    pageLayout->addWidget(mProfileToolBar);
 | 
			
		||||
 | 
			
		||||
    // Create a dialog for the new profile name input
 | 
			
		||||
| 
						 | 
				
			
			@ -164,15 +69,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent)
 | 
			
		|||
 | 
			
		||||
    connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString)));
 | 
			
		||||
    
 | 
			
		||||
    connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
 | 
			
		||||
    connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
 | 
			
		||||
 | 
			
		||||
    connect(mMastersModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList)));
 | 
			
		||||
 | 
			
		||||
    connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
 | 
			
		||||
 | 
			
		||||
    connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
 | 
			
		||||
 | 
			
		||||
    connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString)));
 | 
			
		||||
    connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString)));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -202,20 +98,6 @@ void DataFilesPage::createActions()
 | 
			
		|||
    mProfileToolBar->addSeparator();
 | 
			
		||||
    mProfileToolBar->addAction(mNewProfileAction);
 | 
			
		||||
    mProfileToolBar->addAction(mDeleteProfileAction);
 | 
			
		||||
 | 
			
		||||
    // Context menu actions
 | 
			
		||||
    mCheckAction = new QAction(tr("Check selected"), this);
 | 
			
		||||
    connect(mCheckAction, SIGNAL(triggered()), this, SLOT(check()));
 | 
			
		||||
 | 
			
		||||
    mUncheckAction = new QAction(tr("Uncheck selected"), this);
 | 
			
		||||
    connect(mUncheckAction, SIGNAL(triggered()), this, SLOT(uncheck()));
 | 
			
		||||
 | 
			
		||||
    // Context menu for the plugins table
 | 
			
		||||
    mContextMenu = new QMenu(this);
 | 
			
		||||
 | 
			
		||||
    mContextMenu->addAction(mCheckAction);
 | 
			
		||||
    mContextMenu->addAction(mUncheckAction);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesPage::setupConfig()
 | 
			
		||||
| 
						 | 
				
			
			@ -267,10 +149,6 @@ void DataFilesPage::setupConfig()
 | 
			
		|||
 | 
			
		||||
void DataFilesPage::readConfig()
 | 
			
		||||
{
 | 
			
		||||
    // Don't read the config if no masters are found
 | 
			
		||||
    if (mMastersModel->rowCount() < 1)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    QString profile = mProfilesComboBox->currentText();
 | 
			
		||||
    
 | 
			
		||||
    // Make sure we have no groups open
 | 
			
		||||
| 
						 | 
				
			
			@ -291,53 +169,10 @@ void DataFilesPage::readConfig()
 | 
			
		|||
    foreach (const QString &key, childKeys) {
 | 
			
		||||
        const QString keyValue = mLauncherConfig->value(key).toString();
 | 
			
		||||
        
 | 
			
		||||
        if (key.startsWith("Plugin")) {
 | 
			
		||||
            //QStringList checked = mPluginsModel->checkedItems();
 | 
			
		||||
            EsmFile *file = mPluginsModel->findItem(keyValue);
 | 
			
		||||
            QModelIndex index = mPluginsModel->indexFromItem(file);
 | 
			
		||||
 | 
			
		||||
            mPluginsModel->setCheckState(index, Qt::Checked);
 | 
			
		||||
            // Move the row to the top of te view
 | 
			
		||||
            //mPluginsModel->moveRow(index.row(), checked.count());
 | 
			
		||||
            plugins << keyValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (key.startsWith("Master")) {
 | 
			
		||||
            EsmFile *file = mMastersModel->findItem(keyValue);
 | 
			
		||||
            mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked);
 | 
			
		||||
        }
 | 
			
		||||
        mDataFilesList->setCheckState(keyValue, Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qDebug() << plugins;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//    // Set the checked item positions
 | 
			
		||||
//    const QStringList checked = mPluginsModel->checkedItems();
 | 
			
		||||
//    for (int i = 0; i < plugins.size(); ++i) {
 | 
			
		||||
//        EsmFile *file = mPluginsModel->findItem(plugins.at(i));
 | 
			
		||||
//        QModelIndex index = mPluginsModel->indexFromItem(file);
 | 
			
		||||
//        mPluginsModel->moveRow(index.row(), i);
 | 
			
		||||
//        qDebug() << "Moving: " << plugins.at(i) << " from: " << index.row() << " to: " << i << " count: " << checked.count();
 | 
			
		||||
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
    // Iterate over the plugins to set their checkstate and position
 | 
			
		||||
//    for (int i = 0; i < plugins.size(); ++i) {
 | 
			
		||||
//        const QString plugin = plugins.at(i);
 | 
			
		||||
 | 
			
		||||
//        const QList<QStandardItem *> pluginList = mPluginsModel->findItems(plugin);
 | 
			
		||||
 | 
			
		||||
//        if (!pluginList.isEmpty())
 | 
			
		||||
//        {
 | 
			
		||||
//            foreach (const QStandardItem *currentPlugin, pluginList) {
 | 
			
		||||
//                mPluginsModel->setData(currentPlugin->index(), Qt::Checked, Qt::CheckStateRole);
 | 
			
		||||
 | 
			
		||||
//                // Move the plugin to the position specified in the config file
 | 
			
		||||
//                mPluginsModel->insertRow(i, mPluginsModel->takeRow(currentPlugin->row()));
 | 
			
		||||
//            }
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DataFilesPage::showDataFilesWarning()
 | 
			
		||||
| 
						 | 
				
			
			@ -420,43 +255,17 @@ bool DataFilesPage::setupDataFiles()
 | 
			
		|||
    
 | 
			
		||||
    // Set the charset for reading the esm/esp files
 | 
			
		||||
    QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
 | 
			
		||||
    if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) {
 | 
			
		||||
        mMastersModel->setEncoding(encoding);
 | 
			
		||||
        mPluginsModel->setEncoding(encoding);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Add the paths to the respective models
 | 
			
		||||
    for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) {
 | 
			
		||||
        QString path = QString::fromStdString(it->string());
 | 
			
		||||
        path.remove(QChar('\"'));
 | 
			
		||||
        mMastersModel->addMasters(path);
 | 
			
		||||
        mPluginsModel->addPlugins(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Same for the data-local paths
 | 
			
		||||
    for (Files::PathContainer::iterator it = mDataLocal.begin(); it != mDataLocal.end(); ++it) {
 | 
			
		||||
        QString path = QString::fromStdString(it->string());
 | 
			
		||||
        path.remove(QChar('\"'));
 | 
			
		||||
        mMastersModel->addMasters(path);
 | 
			
		||||
        mPluginsModel->addPlugins(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mMastersModel->sort(0);
 | 
			
		||||
    mPluginsModel->sort(0);
 | 
			
		||||
//    mMastersTable->sortByColumn(3, Qt::AscendingOrder);
 | 
			
		||||
//    mPluginsTable->sortByColumn(3, Qt::AscendingOrder);
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    Files::PathContainer paths;
 | 
			
		||||
    paths.insert(paths.end(), mDataDirs.begin(), mDataDirs.end());
 | 
			
		||||
    paths.insert(paths.end(), mDataLocal.begin(), mDataLocal.end());
 | 
			
		||||
    mDataFilesList->setupDataFiles(paths, encoding);
 | 
			
		||||
    readConfig();
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesPage::writeConfig(QString profile)
 | 
			
		||||
{
 | 
			
		||||
    // Don't overwrite the config if no masters are found
 | 
			
		||||
    if (mMastersModel->rowCount() < 1)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string());
 | 
			
		||||
    QDir userPath(pathStr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -579,24 +388,19 @@ void DataFilesPage::writeConfig(QString profile)
 | 
			
		|||
    mLauncherConfig->remove(""); // Clear the subgroup
 | 
			
		||||
 | 
			
		||||
    // Now write the masters to the configs
 | 
			
		||||
    const QStringList masters = mMastersModel->checkedItems();
 | 
			
		||||
 | 
			
		||||
    // We don't use foreach because we need i
 | 
			
		||||
    for (int i = 0; i < masters.size(); ++i) {
 | 
			
		||||
        const QString currentMaster = masters.at(i);
 | 
			
		||||
 | 
			
		||||
        mLauncherConfig->setValue(QString("Master%0").arg(i), currentMaster);
 | 
			
		||||
        gameConfig << "master=" << currentMaster << endl;
 | 
			
		||||
 | 
			
		||||
    const QStringList checkedFiles = mDataFilesList->checkedFiles();
 | 
			
		||||
    for(int i=0; i < checkedFiles.size(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        if (checkedFiles.at(i).lastIndexOf("esm") != -1)
 | 
			
		||||
        {
 | 
			
		||||
            mLauncherConfig->setValue(QString("Master%0").arg(i), checkedFiles.at(i));
 | 
			
		||||
            gameConfig << "master=" << checkedFiles.at(i) << endl;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mLauncherConfig->setValue(QString("Plugin%1").arg(i), checkedFiles.at(i));
 | 
			
		||||
            gameConfig << "plugin=" << checkedFiles.at(i) << endl;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // And finally write all checked plugins
 | 
			
		||||
    const QStringList plugins = mPluginsModel->checkedItems();
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < plugins.size(); ++i) {
 | 
			
		||||
        const QString currentPlugin = plugins.at(i);
 | 
			
		||||
        mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin);
 | 
			
		||||
        gameConfig << "plugin=" << currentPlugin << endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    file.close();
 | 
			
		||||
| 
						 | 
				
			
			@ -670,93 +474,6 @@ void DataFilesPage::deleteProfile()
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesPage::check()
 | 
			
		||||
{
 | 
			
		||||
    // Check the current selection
 | 
			
		||||
    if (!mPluginsTable->selectionModel()->hasSelection()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes();
 | 
			
		||||
 | 
			
		||||
    //sort selection ascending because selectedIndexes returns an unsorted list
 | 
			
		||||
    //qSort(indexes.begin(), indexes.end(), rowSmallerThan);
 | 
			
		||||
 | 
			
		||||
    foreach (const QModelIndex &index, indexes) {
 | 
			
		||||
        if (!index.isValid())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        mPluginsModel->setCheckState(index, Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesPage::uncheck()
 | 
			
		||||
{
 | 
			
		||||
    // uncheck the current selection
 | 
			
		||||
    if (!mPluginsTable->selectionModel()->hasSelection()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes();
 | 
			
		||||
 | 
			
		||||
    //sort selection ascending because selectedIndexes returns an unsorted list
 | 
			
		||||
    //qSort(indexes.begin(), indexes.end(), rowSmallerThan);
 | 
			
		||||
 | 
			
		||||
    foreach (const QModelIndex &index, indexes) {
 | 
			
		||||
        if (!index.isValid())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        mPluginsModel->setCheckState(index, Qt::Unchecked);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesPage::refresh()
 | 
			
		||||
{
 | 
			
		||||
    mPluginsModel->sort(0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Refresh the plugins table
 | 
			
		||||
    mPluginsTable->scrollToTop();
 | 
			
		||||
    writeConfig();
 | 
			
		||||
    readConfig();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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(index);
 | 
			
		||||
 | 
			
		||||
        (mPluginsModel->checkState(sourceIndex) == Qt::Checked)
 | 
			
		||||
                ? mPluginsModel->setCheckState(sourceIndex, Qt::Unchecked)
 | 
			
		||||
                : mPluginsModel->setCheckState(sourceIndex, Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (object->objectName() == QLatin1String("MastersTable")) {
 | 
			
		||||
        (mMastersModel->checkState(index) == Qt::Checked)
 | 
			
		||||
                ? mMastersModel->setCheckState(index, Qt::Unchecked)
 | 
			
		||||
                : mMastersModel->setCheckState(index, Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesPage::filterChanged(const QString filter)
 | 
			
		||||
{
 | 
			
		||||
    QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString);
 | 
			
		||||
    mPluginsProxyModel->setFilterRegExp(regExp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesPage::profileChanged(const QString &previous, const QString ¤t)
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "Profile is changed from: " << previous << " to " << current;
 | 
			
		||||
| 
						 | 
				
			
			@ -780,8 +497,7 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre
 | 
			
		|||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mMastersModel->uncheckAll();
 | 
			
		||||
    mPluginsModel->uncheckAll();
 | 
			
		||||
    mDataFilesList->uncheckAll();
 | 
			
		||||
    readConfig();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -810,35 +526,8 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre
 | 
			
		|||
     // Remove the profile from the combobox
 | 
			
		||||
     mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous));
 | 
			
		||||
 | 
			
		||||
     mMastersModel->uncheckAll();
 | 
			
		||||
     mPluginsModel->uncheckAll();
 | 
			
		||||
     mDataFilesList->uncheckAll();
 | 
			
		||||
     ////mMastersModel->uncheckAll();
 | 
			
		||||
     ////mPluginsModel->uncheckAll();
 | 
			
		||||
     readConfig();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesPage::showContextMenu(const QPoint &point)
 | 
			
		||||
{
 | 
			
		||||
    // Make sure there are plugins in the view
 | 
			
		||||
    if (!mPluginsTable->selectionModel()->hasSelection()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QPoint globalPos = mPluginsTable->mapToGlobal(point);
 | 
			
		||||
 | 
			
		||||
    QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes();
 | 
			
		||||
 | 
			
		||||
    // Show the check/uncheck actions depending on the state of the selected items
 | 
			
		||||
    mUncheckAction->setEnabled(false);
 | 
			
		||||
    mCheckAction->setEnabled(false);
 | 
			
		||||
 | 
			
		||||
    foreach (const QModelIndex &index, indexes) {
 | 
			
		||||
        if (!index.isValid())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
         (mPluginsModel->checkState(index) == Qt::Checked)
 | 
			
		||||
             ? mUncheckAction->setEnabled(true)
 | 
			
		||||
             : mCheckAction->setEnabled(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Show menu
 | 
			
		||||
    mContextMenu->exec(globalPos);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ class ProfilesComboBox;
 | 
			
		|||
class DataFilesModel;
 | 
			
		||||
 | 
			
		||||
class TextInputDialog;
 | 
			
		||||
class DataFilesList;
 | 
			
		||||
 | 
			
		||||
namespace Files { struct ConfigurationManager; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,10 +35,6 @@ public:
 | 
			
		|||
    bool setupDataFiles();
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
    void setCheckState(QModelIndex index);
 | 
			
		||||
 | 
			
		||||
    void filterChanged(const QString filter);
 | 
			
		||||
    void showContextMenu(const QPoint &point);
 | 
			
		||||
    void profileChanged(const QString &previous, const QString ¤t);
 | 
			
		||||
    void profileRenamed(const QString &previous, const QString ¤t);
 | 
			
		||||
    void updateOkButton(const QString &text);
 | 
			
		||||
| 
						 | 
				
			
			@ -49,21 +46,11 @@ public slots:
 | 
			
		|||
//    void moveDown();
 | 
			
		||||
//    void moveTop();
 | 
			
		||||
//    void moveBottom();
 | 
			
		||||
    void check();
 | 
			
		||||
    void uncheck();
 | 
			
		||||
    void refresh();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    DataFilesModel *mMastersModel;
 | 
			
		||||
    DataFilesModel *mPluginsModel;
 | 
			
		||||
 | 
			
		||||
    QSortFilterProxyModel *mPluginsProxyModel;
 | 
			
		||||
 | 
			
		||||
    QTableView *mMastersTable;
 | 
			
		||||
    QTableView *mPluginsTable;
 | 
			
		||||
    DataFilesList *mDataFilesList;
 | 
			
		||||
 | 
			
		||||
    QToolBar *mProfileToolBar;
 | 
			
		||||
    QMenu *mContextMenu;
 | 
			
		||||
 | 
			
		||||
    QAction *mNewProfileAction;
 | 
			
		||||
    QAction *mDeleteProfileAction;
 | 
			
		||||
| 
						 | 
				
			
			@ -72,8 +59,6 @@ private:
 | 
			
		|||
//    QAction *mMoveDownAction;
 | 
			
		||||
//    QAction *mMoveTopAction;
 | 
			
		||||
//    QAction *mMoveBottomAction;
 | 
			
		||||
    QAction *mCheckAction;
 | 
			
		||||
    QAction *mUncheckAction;
 | 
			
		||||
 | 
			
		||||
    Files::ConfigurationManager &mCfgMgr;
 | 
			
		||||
    Files::PathContainer mDataDirs;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,8 +8,7 @@
 | 
			
		|||
#include <components/files/configurationmanager.hpp>
 | 
			
		||||
#include <components/files/ogreplugin.hpp>
 | 
			
		||||
#include <components/settings/settings.hpp>
 | 
			
		||||
 | 
			
		||||
#include "utils/naturalsort.hpp"
 | 
			
		||||
#include <components/fileorderlist/utils/naturalsort.hpp>
 | 
			
		||||
 | 
			
		||||
#include "graphicspage.hpp"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
#include <QVBoxLayout>
 | 
			
		||||
#include <QValidator>
 | 
			
		||||
 | 
			
		||||
#include "lineedit.hpp"
 | 
			
		||||
#include <components/fileorderlist/utils/lineedit.hpp>
 | 
			
		||||
 | 
			
		||||
#include "textinputdialog.hpp"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ opencs_units (model/world
 | 
			
		|||
    idtable idtableproxymodel
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
opencs_units_noqt (model/world
 | 
			
		||||
    universalid data record idcollection commands columnbase
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			@ -40,9 +41,10 @@ opencs_units_noqt (model/tools
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
opencs_units (view/doc
 | 
			
		||||
    viewmanager view operations operation subview
 | 
			
		||||
    viewmanager view operations operation subview startup opendialog
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
opencs_units_noqt (view/doc
 | 
			
		||||
    subviewfactory
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,39 +11,52 @@
 | 
			
		|||
CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0)
 | 
			
		||||
{
 | 
			
		||||
    connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ()));
 | 
			
		||||
    connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
 | 
			
		||||
 | 
			
		||||
    connect (&mStartup, SIGNAL (createDocument()), this, SLOT (createDocument ()));
 | 
			
		||||
    connect (&mStartup, SIGNAL (loadDocument()), this, SLOT (loadDocument ()));
 | 
			
		||||
 | 
			
		||||
    connect (&mOpenDialog, SIGNAL(accepted()), this, SLOT(openFiles()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CS::Editor::createDocument()
 | 
			
		||||
{
 | 
			
		||||
    mStartup.hide();
 | 
			
		||||
 | 
			
		||||
    /// \todo open the ESX picker instead
 | 
			
		||||
 | 
			
		||||
    std::ostringstream stream;
 | 
			
		||||
 | 
			
		||||
    stream << "NewDocument" << (++mNewDocumentIndex);
 | 
			
		||||
 | 
			
		||||
    CSMDoc::Document *document = mDocumentManager.addDocument (stream.str());
 | 
			
		||||
    std::vector<boost::filesystem::path> files;
 | 
			
		||||
    files.push_back (stream.str());
 | 
			
		||||
 | 
			
		||||
    static const char *sGlobals[] =
 | 
			
		||||
    {
 | 
			
		||||
            "Day", "DaysPassed", "GameHour", "Month", "PCRace", "PCVampire", "PCWerewolf", "PCYear", 0
 | 
			
		||||
    };
 | 
			
		||||
    CSMDoc::Document *document = mDocumentManager.addDocument (files, true);
 | 
			
		||||
 | 
			
		||||
    for (int i=0; sGlobals[i]; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        ESM::Global record;
 | 
			
		||||
        record.mId = sGlobals[i];
 | 
			
		||||
        record.mValue = i==0 ? 1 : 0;
 | 
			
		||||
        record.mType = ESM::VT_Float;
 | 
			
		||||
        document->getData().getGlobals().add (record);
 | 
			
		||||
    }
 | 
			
		||||
    mViewManager.addView (document);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    document->getData().merge(); /// \todo remove once proper ESX loading is implemented
 | 
			
		||||
void CS::Editor::loadDocument()
 | 
			
		||||
{
 | 
			
		||||
    mStartup.hide();
 | 
			
		||||
    mOpenDialog.show();
 | 
			
		||||
    mOpenDialog.raise();
 | 
			
		||||
    mOpenDialog.activateWindow();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CS::Editor::openFiles()
 | 
			
		||||
{
 | 
			
		||||
    std::vector<boost::filesystem::path> paths;
 | 
			
		||||
    mOpenDialog.getFileList(paths);
 | 
			
		||||
    CSMDoc::Document *document = mDocumentManager.addDocument(paths, false);
 | 
			
		||||
 | 
			
		||||
    mViewManager.addView (document);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CS::Editor::run()
 | 
			
		||||
{
 | 
			
		||||
    /// \todo Instead of creating an empty document, open a small welcome dialogue window with buttons for new/load/recent projects
 | 
			
		||||
    createDocument();
 | 
			
		||||
    mStartup.show();
 | 
			
		||||
 | 
			
		||||
    return QApplication::exec();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,10 @@
 | 
			
		|||
#include <QObject>
 | 
			
		||||
 | 
			
		||||
#include "model/doc/documentmanager.hpp"
 | 
			
		||||
 | 
			
		||||
#include "view/doc/viewmanager.hpp"
 | 
			
		||||
#include "view/doc/startup.hpp"
 | 
			
		||||
#include "view/doc/opendialog.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CS
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +19,8 @@ namespace CS
 | 
			
		|||
 | 
			
		||||
            CSMDoc::DocumentManager mDocumentManager;
 | 
			
		||||
            CSVDoc::ViewManager mViewManager;
 | 
			
		||||
            CSVDoc::StartupDialogue mStartup;
 | 
			
		||||
            OpenDialog mOpenDialog;
 | 
			
		||||
 | 
			
		||||
            // not implemented
 | 
			
		||||
            Editor (const Editor&);
 | 
			
		||||
| 
						 | 
				
			
			@ -28,9 +33,12 @@ namespace CS
 | 
			
		|||
            int run();
 | 
			
		||||
            ///< \return error status
 | 
			
		||||
 | 
			
		||||
        public slots:
 | 
			
		||||
        private slots:
 | 
			
		||||
 | 
			
		||||
            void createDocument();
 | 
			
		||||
 | 
			
		||||
            void loadDocument();
 | 
			
		||||
            void openFiles();
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,66 @@
 | 
			
		|||
 | 
			
		||||
#include "document.hpp"
 | 
			
		||||
 | 
			
		||||
CSMDoc::Document::Document (const std::string& name)
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
 | 
			
		||||
    const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
 | 
			
		||||
{
 | 
			
		||||
    assert (begin!=end);
 | 
			
		||||
 | 
			
		||||
    std::vector<boost::filesystem::path>::const_iterator end2 (end);
 | 
			
		||||
 | 
			
		||||
    if (lastAsModified)
 | 
			
		||||
        --end2;
 | 
			
		||||
 | 
			
		||||
    for (std::vector<boost::filesystem::path>::const_iterator iter (begin); iter!=end2; ++iter)
 | 
			
		||||
        getData().loadFile (*iter, true);
 | 
			
		||||
 | 
			
		||||
    if (lastAsModified)
 | 
			
		||||
        getData().loadFile (*end2, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSMDoc::Document::createBase()
 | 
			
		||||
{
 | 
			
		||||
    static const char *sGlobals[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Day", "DaysPassed", "GameHour", "Month", "PCRace", "PCVampire", "PCWerewolf", "PCYear", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for (int i=0; sGlobals[i]; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        ESM::Global record;
 | 
			
		||||
        record.mId = sGlobals[i];
 | 
			
		||||
        record.mValue = i==0 ? 1 : 0;
 | 
			
		||||
        record.mType = ESM::VT_Float;
 | 
			
		||||
        getData().getGlobals().add (record);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, bool new_)
 | 
			
		||||
: mTools (mData)
 | 
			
		||||
{
 | 
			
		||||
    mName = name; ///< \todo replace with ESX list
 | 
			
		||||
    if (files.empty())
 | 
			
		||||
        throw std::runtime_error ("Empty content file sequence");
 | 
			
		||||
 | 
			
		||||
    /// \todo adjust last file name:
 | 
			
		||||
    /// \li make sure it is located in the data-local directory (adjust path if necessary)
 | 
			
		||||
    /// \li make sure the extension matches the new scheme (change it if necesarry)
 | 
			
		||||
 | 
			
		||||
    mName = files.back().filename().string();
 | 
			
		||||
 | 
			
		||||
    if (files.size()>1 || !new_)
 | 
			
		||||
    {
 | 
			
		||||
        std::vector<boost::filesystem::path>::const_iterator end = files.end();
 | 
			
		||||
 | 
			
		||||
        if (new_)
 | 
			
		||||
            --end;
 | 
			
		||||
 | 
			
		||||
        load (files.begin(), end, !new_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (new_ && files.size()==1)
 | 
			
		||||
        createBase();
 | 
			
		||||
 | 
			
		||||
    connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@
 | 
			
		|||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include <boost/filesystem/path.hpp>
 | 
			
		||||
 | 
			
		||||
#include <QUndoStack>
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
| 
						 | 
				
			
			@ -38,10 +40,15 @@ namespace CSMDoc
 | 
			
		|||
            Document (const Document&);
 | 
			
		||||
            Document& operator= (const Document&);
 | 
			
		||||
 | 
			
		||||
            void load (const std::vector<boost::filesystem::path>::const_iterator& begin,
 | 
			
		||||
                const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified);
 | 
			
		||||
            ///< \param lastAsModified Store the last file in Modified instead of merging it into Base.
 | 
			
		||||
 | 
			
		||||
            void createBase();
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            Document (const std::string& name);
 | 
			
		||||
            ///< \todo replace name with ESX list
 | 
			
		||||
            Document (const std::vector<boost::filesystem::path>& files, bool new_);
 | 
			
		||||
 | 
			
		||||
            QUndoStack& getUndoStack();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,9 +14,10 @@ CSMDoc::DocumentManager::~DocumentManager()
 | 
			
		|||
        delete *iter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::string& name)
 | 
			
		||||
CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files,
 | 
			
		||||
    bool new_)
 | 
			
		||||
{
 | 
			
		||||
    Document *document = new Document (name);
 | 
			
		||||
    Document *document = new Document (files, new_);
 | 
			
		||||
 | 
			
		||||
    mDocuments.push_back (document);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,8 @@
 | 
			
		|||
#include <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include <boost/filesystem/path.hpp>
 | 
			
		||||
 | 
			
		||||
namespace CSMDoc
 | 
			
		||||
{
 | 
			
		||||
    class Document;
 | 
			
		||||
| 
						 | 
				
			
			@ -21,8 +23,11 @@ namespace CSMDoc
 | 
			
		|||
 | 
			
		||||
            ~DocumentManager();
 | 
			
		||||
 | 
			
		||||
            Document *addDocument (const std::string& name);
 | 
			
		||||
            Document *addDocument (const std::vector<boost::filesystem::path>& files, bool new_);
 | 
			
		||||
            ///< The ownership of the returned document is not transferred to the caller.
 | 
			
		||||
            ///
 | 
			
		||||
            /// \param new_ Do not load the last content file in \a files and instead create in an
 | 
			
		||||
            /// appropriate way.
 | 
			
		||||
 | 
			
		||||
            bool removeDocument (Document *document);
 | 
			
		||||
            ///< \return last document removed?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,8 @@ namespace CSMWorld
 | 
			
		|||
        {
 | 
			
		||||
            Display_String,
 | 
			
		||||
            Display_Integer,
 | 
			
		||||
            Display_Float
 | 
			
		||||
            Display_Float,
 | 
			
		||||
            Display_Var
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        std::string mTitle;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,9 +17,9 @@ namespace CSMWorld
 | 
			
		|||
 | 
			
		||||
        virtual void set (Record<ESXRecordT>& record, const QVariant& data)
 | 
			
		||||
        {
 | 
			
		||||
            ESXRecordT base = record.getBase();
 | 
			
		||||
            base.mValue = data.toFloat();
 | 
			
		||||
            record.setModified (base);
 | 
			
		||||
            ESXRecordT record2 = record.get();
 | 
			
		||||
            record2.mValue = data.toFloat();
 | 
			
		||||
            record.setModified (record2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual bool isEditable() const
 | 
			
		||||
| 
						 | 
				
			
			@ -91,6 +91,68 @@ namespace CSMWorld
 | 
			
		|||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template<typename ESXRecordT>
 | 
			
		||||
    struct VarTypeColumn : public Column<ESXRecordT>
 | 
			
		||||
    {
 | 
			
		||||
        VarTypeColumn() : Column<ESXRecordT> ("Type", ColumnBase::Display_Integer) {}
 | 
			
		||||
 | 
			
		||||
        virtual QVariant get (const Record<ESXRecordT>& record) const
 | 
			
		||||
        {
 | 
			
		||||
            return static_cast<int> (record.get().mType);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void set (Record<ESXRecordT>& record, const QVariant& data)
 | 
			
		||||
        {
 | 
			
		||||
            ESXRecordT record2 = record.get();
 | 
			
		||||
            record2.mType = static_cast<ESM::VarType> (data.toInt());
 | 
			
		||||
            record.setModified (record2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual bool isEditable() const
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template<typename ESXRecordT>
 | 
			
		||||
    struct VarValueColumn : public Column<ESXRecordT>
 | 
			
		||||
    {
 | 
			
		||||
        VarValueColumn() : Column<ESXRecordT> ("Value", ColumnBase::Display_Var) {}
 | 
			
		||||
 | 
			
		||||
        virtual QVariant get (const Record<ESXRecordT>& record) const
 | 
			
		||||
        {
 | 
			
		||||
            switch (record.get().mType)
 | 
			
		||||
            {
 | 
			
		||||
                case ESM::VT_String: return record.get().mStr.c_str(); break;
 | 
			
		||||
                case ESM::VT_Int: return record.get().mI; break;
 | 
			
		||||
                case ESM::VT_Float: return record.get().mF; break;
 | 
			
		||||
 | 
			
		||||
                default: return QVariant();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void set (Record<ESXRecordT>& record, const QVariant& data)
 | 
			
		||||
        {
 | 
			
		||||
            ESXRecordT record2 = record.get();
 | 
			
		||||
 | 
			
		||||
            switch (record2.mType)
 | 
			
		||||
            {
 | 
			
		||||
                case ESM::VT_String: record2.mStr = data.toString().toUtf8().constData(); break;
 | 
			
		||||
                case ESM::VT_Int: record2.mI = data.toInt(); break;
 | 
			
		||||
                case ESM::VT_Float: record2.mF = data.toFloat(); break;
 | 
			
		||||
 | 
			
		||||
                default: break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            record.setModified (record2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual bool isEditable() const
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
 | 
			
		||||
#include <QAbstractTableModel>
 | 
			
		||||
 | 
			
		||||
#include <components/esm/esmreader.hpp>
 | 
			
		||||
#include <components/esm/loadglob.hpp>
 | 
			
		||||
 | 
			
		||||
#include "idtable.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +28,14 @@ CSMWorld::Data::Data()
 | 
			
		|||
    mGlobals.addColumn (new FixedRecordTypeColumn<ESM::Global> (UniversalId::Type_Global));
 | 
			
		||||
    mGlobals.addColumn (new FloatValueColumn<ESM::Global>);
 | 
			
		||||
 | 
			
		||||
    mGmsts.addColumn (new StringIdColumn<ESM::GameSetting>);
 | 
			
		||||
    mGmsts.addColumn (new RecordStateColumn<ESM::GameSetting>);
 | 
			
		||||
    mGmsts.addColumn (new FixedRecordTypeColumn<ESM::GameSetting> (UniversalId::Type_Gmst));
 | 
			
		||||
    mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting>);
 | 
			
		||||
    mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>);
 | 
			
		||||
 | 
			
		||||
    addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
 | 
			
		||||
    addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSMWorld::Data::~Data()
 | 
			
		||||
| 
						 | 
				
			
			@ -60,3 +68,30 @@ void CSMWorld::Data::merge()
 | 
			
		|||
{
 | 
			
		||||
    mGlobals.merge();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
 | 
			
		||||
{
 | 
			
		||||
    ESM::ESMReader reader;
 | 
			
		||||
    /// \todo set encoder
 | 
			
		||||
    reader.open (path.string());
 | 
			
		||||
 | 
			
		||||
    // Note: We do not need to send update signals here, because at this point the model is not connected
 | 
			
		||||
    // to any view.
 | 
			
		||||
    while (reader.hasMoreRecs())
 | 
			
		||||
    {
 | 
			
		||||
        ESM::NAME n = reader.getRecName();
 | 
			
		||||
        reader.getRecHeader();
 | 
			
		||||
 | 
			
		||||
        switch (n.val)
 | 
			
		||||
        {
 | 
			
		||||
            case ESM::REC_GLOB: mGlobals.load (reader, base); break;
 | 
			
		||||
            case ESM::REC_GMST: mGmsts.load (reader, base); break;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
 | 
			
		||||
                /// \todo throw an exception instead, once all records are implemented
 | 
			
		||||
                reader.skipRecord();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,10 @@
 | 
			
		|||
#include <map>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <boost/filesystem/path.hpp>
 | 
			
		||||
 | 
			
		||||
#include <components/esm/loadglob.hpp>
 | 
			
		||||
#include <components/esm/loadgmst.hpp>
 | 
			
		||||
 | 
			
		||||
#include "idcollection.hpp"
 | 
			
		||||
#include "universalid.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +19,7 @@ namespace CSMWorld
 | 
			
		|||
    class Data
 | 
			
		||||
    {
 | 
			
		||||
            IdCollection<ESM::Global> mGlobals;
 | 
			
		||||
            IdCollection<ESM::GameSetting> mGmsts;
 | 
			
		||||
            std::vector<QAbstractTableModel *> mModels;
 | 
			
		||||
            std::map<UniversalId::Type, QAbstractTableModel *> mModelIndex;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,6 +48,9 @@ namespace CSMWorld
 | 
			
		|||
 | 
			
		||||
            void merge();
 | 
			
		||||
            ///< Merge modified into base.
 | 
			
		||||
 | 
			
		||||
            void loadFile (const boost::filesystem::path& path, bool base);
 | 
			
		||||
            ///< Merging content of a file into base or modified.
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,9 +11,12 @@
 | 
			
		|||
 | 
			
		||||
#include <QVariant>
 | 
			
		||||
 | 
			
		||||
#include "columnbase.hpp"
 | 
			
		||||
#include <components/esm/esmreader.hpp>
 | 
			
		||||
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
#include "columnbase.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CSMWorld
 | 
			
		||||
{
 | 
			
		||||
    class IdCollectionBase
 | 
			
		||||
| 
						 | 
				
			
			@ -67,9 +70,11 @@ namespace CSMWorld
 | 
			
		|||
            virtual std::string getId (const RecordBase& record) const = 0;
 | 
			
		||||
            ///< Return ID for \a record.
 | 
			
		||||
            ///
 | 
			
		||||
            /// \attention Throw san exception, if the type of \a record does not match.
 | 
			
		||||
            /// \attention Throws an exception, if the type of \a record does not match.
 | 
			
		||||
 | 
			
		||||
            virtual const RecordBase& getRecord (const std::string& id) const = 0;
 | 
			
		||||
 | 
			
		||||
            virtual void load (ESM::ESMReader& reader, bool base) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ///< \brief Collection of ID-based records
 | 
			
		||||
| 
						 | 
				
			
			@ -136,6 +141,8 @@ namespace CSMWorld
 | 
			
		|||
 | 
			
		||||
            virtual const RecordBase& getRecord (const std::string& id) const;
 | 
			
		||||
 | 
			
		||||
            virtual void load (ESM::ESMReader& reader, bool base);
 | 
			
		||||
 | 
			
		||||
            void addColumn (Column<ESXRecordT> *column);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -309,6 +316,62 @@ namespace CSMWorld
 | 
			
		|||
        return (record2.isModified() ? record2.mModified : record2.mBase).mId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename ESXRecordT>
 | 
			
		||||
    void IdCollection<ESXRecordT>::load (ESM::ESMReader& reader, bool base)
 | 
			
		||||
    {
 | 
			
		||||
        std::string id = reader.getHNOString ("NAME");
 | 
			
		||||
 | 
			
		||||
        int index = searchId (id);
 | 
			
		||||
 | 
			
		||||
        if (reader.isNextSub ("DELE"))
 | 
			
		||||
        {
 | 
			
		||||
            reader.skipRecord();
 | 
			
		||||
 | 
			
		||||
            if (index==-1)
 | 
			
		||||
            {
 | 
			
		||||
                // deleting a record that does not exist
 | 
			
		||||
 | 
			
		||||
                // ignore it for now
 | 
			
		||||
 | 
			
		||||
                /// \todo report the problem to the user
 | 
			
		||||
            }
 | 
			
		||||
            else if (base)
 | 
			
		||||
            {
 | 
			
		||||
                removeRows (index, 1);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mRecords[index].mState = RecordBase::State_Deleted;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            ESXRecordT record;
 | 
			
		||||
            record.mId = id;
 | 
			
		||||
            record.load (reader);
 | 
			
		||||
 | 
			
		||||
            if (index==-1)
 | 
			
		||||
            {
 | 
			
		||||
                // new record
 | 
			
		||||
                Record<ESXRecordT> record2;
 | 
			
		||||
                record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
 | 
			
		||||
                (base ? record2.mBase : record2.mModified) = record;
 | 
			
		||||
 | 
			
		||||
                appendRecord (record2);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // old record
 | 
			
		||||
                Record<ESXRecordT>& record2 = mRecords[index];
 | 
			
		||||
 | 
			
		||||
                if (base)
 | 
			
		||||
                    record2.mBase = record;
 | 
			
		||||
                else
 | 
			
		||||
                    record2.setModified (record);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename ESXRecordT>
 | 
			
		||||
    const RecordBase& IdCollection<ESXRecordT>::getRecord (const std::string& id) const
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ namespace
 | 
			
		|||
    {
 | 
			
		||||
        { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" },
 | 
			
		||||
        { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" },
 | 
			
		||||
        { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" },
 | 
			
		||||
 | 
			
		||||
        { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +26,7 @@ namespace
 | 
			
		|||
    static const TypeData sIdArg[] =
 | 
			
		||||
    {
 | 
			
		||||
        { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" },
 | 
			
		||||
        { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" },
 | 
			
		||||
 | 
			
		||||
        { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,12 +33,12 @@ namespace CSMWorld
 | 
			
		|||
            enum Type
 | 
			
		||||
            {
 | 
			
		||||
                Type_None,
 | 
			
		||||
 | 
			
		||||
                Type_Globals,
 | 
			
		||||
 | 
			
		||||
                Type_Global,
 | 
			
		||||
                Type_VerificationResults,
 | 
			
		||||
                Type_Gmsts,
 | 
			
		||||
                Type_Gmst
 | 
			
		||||
 | 
			
		||||
                Type_VerificationResults
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										62
									
								
								apps/opencs/view/doc/opendialog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								apps/opencs/view/doc/opendialog.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
#include <QVBoxLayout>
 | 
			
		||||
#include <QDialogButtonBox>
 | 
			
		||||
 | 
			
		||||
#include <components/fileorderlist/datafileslist.hpp>
 | 
			
		||||
 | 
			
		||||
#include "opendialog.hpp"
 | 
			
		||||
 | 
			
		||||
OpenDialog::OpenDialog(QWidget * parent) : QDialog(parent)
 | 
			
		||||
{
 | 
			
		||||
    QVBoxLayout *layout = new QVBoxLayout(this);
 | 
			
		||||
    mFileSelector = new DataFilesList(mCfgMgr, this);
 | 
			
		||||
    layout->addWidget(mFileSelector);
 | 
			
		||||
    
 | 
			
		||||
    //FIXME - same as DataFilesPage::setupDataFiles
 | 
			
		||||
    // We use the Configuration Manager to retrieve the configuration values
 | 
			
		||||
    boost::program_options::variables_map variables;
 | 
			
		||||
    boost::program_options::options_description desc;
 | 
			
		||||
    
 | 
			
		||||
    desc.add_options()
 | 
			
		||||
    ("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
 | 
			
		||||
    ("data-local", boost::program_options::value<std::string>()->default_value(""))
 | 
			
		||||
    ("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
 | 
			
		||||
    ("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
 | 
			
		||||
    
 | 
			
		||||
    boost::program_options::notify(variables);
 | 
			
		||||
    
 | 
			
		||||
    mCfgMgr.readConfiguration(variables, desc);
 | 
			
		||||
    
 | 
			
		||||
    Files::PathContainer mDataDirs, mDataLocal;
 | 
			
		||||
    if (!variables["data"].empty()) {
 | 
			
		||||
        mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    std::string local = variables["data-local"].as<std::string>();
 | 
			
		||||
    if (!local.empty()) {
 | 
			
		||||
        mDataLocal.push_back(Files::PathContainer::value_type(local));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    mCfgMgr.processPaths(mDataDirs);
 | 
			
		||||
    mCfgMgr.processPaths(mDataLocal);
 | 
			
		||||
    
 | 
			
		||||
    // Set the charset for reading the esm/esp files
 | 
			
		||||
    QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
 | 
			
		||||
    
 | 
			
		||||
    Files::PathContainer dataDirs;
 | 
			
		||||
    dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end());
 | 
			
		||||
    dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end());
 | 
			
		||||
    mFileSelector->setupDataFiles(dataDirs, encoding);
 | 
			
		||||
    
 | 
			
		||||
    buttonBox = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel, Qt::Horizontal, this);
 | 
			
		||||
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
 | 
			
		||||
    connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
 | 
			
		||||
    layout->addWidget(buttonBox);
 | 
			
		||||
    
 | 
			
		||||
    setLayout(layout);
 | 
			
		||||
    setWindowTitle(tr("Open"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenDialog::getFileList(std::vector<boost::filesystem::path>& paths)
 | 
			
		||||
{
 | 
			
		||||
    mFileSelector->selectedFiles(paths);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								apps/opencs/view/doc/opendialog.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								apps/opencs/view/doc/opendialog.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
#include <qdialog.h>
 | 
			
		||||
#include <components/files/configurationmanager.hpp>
 | 
			
		||||
 | 
			
		||||
class DataFilesList;
 | 
			
		||||
class QDialogButtonBox;
 | 
			
		||||
 | 
			
		||||
class OpenDialog : public QDialog {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    OpenDialog(QWidget * parent = 0);
 | 
			
		||||
    
 | 
			
		||||
    void getFileList(std::vector<boost::filesystem::path>& paths);
 | 
			
		||||
private:
 | 
			
		||||
    DataFilesList * mFileSelector;
 | 
			
		||||
    QDialogButtonBox * buttonBox;
 | 
			
		||||
    Files::ConfigurationManager mCfgMgr;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										20
									
								
								apps/opencs/view/doc/startup.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								apps/opencs/view/doc/startup.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
 | 
			
		||||
#include "startup.hpp"
 | 
			
		||||
 | 
			
		||||
#include <QPushButton>
 | 
			
		||||
#include <QHBoxLayout>
 | 
			
		||||
 | 
			
		||||
CSVDoc::StartupDialogue::StartupDialogue()
 | 
			
		||||
{
 | 
			
		||||
    QHBoxLayout *layout = new QHBoxLayout (this);
 | 
			
		||||
 | 
			
		||||
    QPushButton *createDocument = new QPushButton ("new", this);
 | 
			
		||||
    connect (createDocument, SIGNAL (clicked()), this, SIGNAL (createDocument()));
 | 
			
		||||
    layout->addWidget (createDocument);
 | 
			
		||||
 | 
			
		||||
    QPushButton *loadDocument = new QPushButton ("load", this);
 | 
			
		||||
    connect (loadDocument, SIGNAL (clicked()), this, SIGNAL (loadDocument()));
 | 
			
		||||
    layout->addWidget (loadDocument);
 | 
			
		||||
 | 
			
		||||
    setLayout (layout);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								apps/opencs/view/doc/startup.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								apps/opencs/view/doc/startup.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
#ifndef CSV_DOC_STARTUP_H
 | 
			
		||||
#define CSV_DOC_STARTUP_H
 | 
			
		||||
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
 | 
			
		||||
namespace CSVDoc
 | 
			
		||||
{
 | 
			
		||||
    class StartupDialogue : public QWidget
 | 
			
		||||
    {
 | 
			
		||||
        Q_OBJECT
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            StartupDialogue();
 | 
			
		||||
 | 
			
		||||
        signals:
 | 
			
		||||
 | 
			
		||||
            void createDocument();
 | 
			
		||||
 | 
			
		||||
            void loadDocument();
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +32,10 @@ void CSVDoc::View::setupFileMenu()
 | 
			
		|||
    connect (new_, SIGNAL (triggered()), this, SIGNAL (newDocumentRequest()));
 | 
			
		||||
    file->addAction (new_);
 | 
			
		||||
 | 
			
		||||
    QAction *open = new QAction (tr ("&Open"), this);
 | 
			
		||||
    connect (open, SIGNAL (triggered()), this, SIGNAL (loadDocumentRequest()));
 | 
			
		||||
    file->addAction (open);
 | 
			
		||||
 | 
			
		||||
    mSave = new QAction (tr ("&Save"), this);
 | 
			
		||||
    connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
 | 
			
		||||
    file->addAction (mSave);
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +71,10 @@ void CSVDoc::View::setupWorldMenu()
 | 
			
		|||
    connect (globals, SIGNAL (triggered()), this, SLOT (addGlobalsSubView()));
 | 
			
		||||
    world->addAction (globals);
 | 
			
		||||
 | 
			
		||||
    QAction *gmsts = new QAction (tr ("Game settings"), this);
 | 
			
		||||
    connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView()));
 | 
			
		||||
    world->addAction (gmsts);
 | 
			
		||||
 | 
			
		||||
    mVerify = new QAction (tr ("&Verify"), this);
 | 
			
		||||
    connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
 | 
			
		||||
    world->addAction (mVerify);
 | 
			
		||||
| 
						 | 
				
			
			@ -214,3 +222,8 @@ void CSVDoc::View::addGlobalsSubView()
 | 
			
		|||
{
 | 
			
		||||
    addSubView (CSMWorld::UniversalId::Type_Globals);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSVDoc::View::addGmstsSubView()
 | 
			
		||||
{
 | 
			
		||||
    addSubView (CSMWorld::UniversalId::Type_Gmsts);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +84,8 @@ namespace CSVDoc
 | 
			
		|||
 | 
			
		||||
            void newDocumentRequest();
 | 
			
		||||
 | 
			
		||||
            void loadDocumentRequest();
 | 
			
		||||
 | 
			
		||||
        public slots:
 | 
			
		||||
 | 
			
		||||
            void addSubView (const CSMWorld::UniversalId& id);
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +99,8 @@ namespace CSVDoc
 | 
			
		|||
            void verify();
 | 
			
		||||
 | 
			
		||||
            void addGlobalsSubView();
 | 
			
		||||
 | 
			
		||||
            void addGmstsSubView();
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,6 +57,7 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
 | 
			
		|||
    view->show();
 | 
			
		||||
 | 
			
		||||
    connect (view, SIGNAL (newDocumentRequest ()), this, SIGNAL (newDocumentRequest()));
 | 
			
		||||
    connect (view, SIGNAL (loadDocumentRequest ()), this, SIGNAL (loadDocumentRequest()));
 | 
			
		||||
 | 
			
		||||
    updateIndices();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,8 @@ namespace CSVDoc
 | 
			
		|||
 | 
			
		||||
            void newDocumentRequest();
 | 
			
		||||
 | 
			
		||||
            void loadDocumentRequest();
 | 
			
		||||
 | 
			
		||||
        private slots:
 | 
			
		||||
 | 
			
		||||
            void documentStateChanged (int state, CSMDoc::Document *document);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,6 +64,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
 | 
			
		|||
                        /// \todo configure widget properly (range, format?)
 | 
			
		||||
                        layout->addWidget (widget = new QDoubleSpinBox, i, 1);
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                    default: break; // silence warnings for other times for now
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +78,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
 | 
			
		|||
 | 
			
		||||
                        layout->addWidget (widget = new QLabel, i, 1);
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                    default: break; // silence warnings for other times for now
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
 | 
			
		|||
    manager.add (CSMWorld::UniversalId::Type_Globals,
 | 
			
		||||
        new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (true));
 | 
			
		||||
 | 
			
		||||
    manager.add (CSMWorld::UniversalId::Type_Gmsts,
 | 
			
		||||
        new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
 | 
			
		||||
 | 
			
		||||
    manager.add (CSMWorld::UniversalId::Type_Global,
 | 
			
		||||
        new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +23,22 @@ endforeach (u)
 | 
			
		|||
source_group ("components\\${dir}" FILES ${files})
 | 
			
		||||
endmacro (add_component_dir)
 | 
			
		||||
 | 
			
		||||
macro (add_component_qt_dir dir)
 | 
			
		||||
set (files)
 | 
			
		||||
foreach (u ${ARGN})
 | 
			
		||||
file (GLOB ALL ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.[ch]pp")
 | 
			
		||||
foreach (f ${ALL})
 | 
			
		||||
list (APPEND files "${f}")
 | 
			
		||||
list (APPEND COMPONENT_FILES "${f}")
 | 
			
		||||
endforeach (f)
 | 
			
		||||
file (GLOB MOC_H ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.hpp")
 | 
			
		||||
foreach (fi ${MOC_H})
 | 
			
		||||
list (APPEND COMPONENT_MOC_FILES "${fi}")
 | 
			
		||||
endforeach (fi)
 | 
			
		||||
endforeach (u)
 | 
			
		||||
source_group ("components\\${dir}" FILES ${files})
 | 
			
		||||
endmacro (add_component_qt_dir)
 | 
			
		||||
 | 
			
		||||
macro (copy_all_files source_dir destination_dir files)
 | 
			
		||||
foreach (f ${files})
 | 
			
		||||
get_filename_component(filename ${f} NAME)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,9 +66,21 @@ add_component_dir (translation
 | 
			
		|||
    translation
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
find_package(Qt4 COMPONENTS QtCore QtGui)
 | 
			
		||||
 | 
			
		||||
if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY)
 | 
			
		||||
   add_component_qt_dir (fileorderlist
 | 
			
		||||
       datafileslist model/modelitem model/datafilesmodel model/esm/esmfile
 | 
			
		||||
       utils/filedialog utils/lineedit utils/naturalsort
 | 
			
		||||
       )
 | 
			
		||||
 | 
			
		||||
   include(${QT_USE_FILE})
 | 
			
		||||
   QT4_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES})
 | 
			
		||||
endif(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY)
 | 
			
		||||
 | 
			
		||||
include_directories(${BULLET_INCLUDE_DIRS})
 | 
			
		||||
 | 
			
		||||
add_library(components STATIC ${COMPONENT_FILES})
 | 
			
		||||
add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS})
 | 
			
		||||
 | 
			
		||||
target_link_libraries(components ${Boost_LIBRARIES} ${OGRE_LIBRARIES})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,4 +80,25 @@ std::string GameSetting::getString() const
 | 
			
		|||
    throw std::runtime_error ("GMST " + mId + " is not a string");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    void GameSetting::blank()
 | 
			
		||||
    {
 | 
			
		||||
        mStr.clear();
 | 
			
		||||
        mI = 0;
 | 
			
		||||
        mF = 0;
 | 
			
		||||
        mType = VT_Float;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator== (const GameSetting& left, const GameSetting& right)
 | 
			
		||||
    {
 | 
			
		||||
        if (left.mType!=right.mType)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        switch (left.mType)
 | 
			
		||||
        {
 | 
			
		||||
            case VT_Float: return left.mF==right.mF;
 | 
			
		||||
            case VT_Int: return left.mI==right.mI;
 | 
			
		||||
            case VT_String: return left.mStr==right.mStr;
 | 
			
		||||
            default: return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,11 @@ struct GameSetting
 | 
			
		|||
    ///< Throwns an exception if GMST is not of type string.
 | 
			
		||||
 | 
			
		||||
    void save(ESMWriter &esm);
 | 
			
		||||
 | 
			
		||||
    void blank();
 | 
			
		||||
    ///< Set record to default state (does not touch the ID).
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    bool operator== (const GameSetting& left, const GameSetting& right);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										351
									
								
								components/fileorderlist/datafileslist.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								components/fileorderlist/datafileslist.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,351 @@
 | 
			
		|||
#include <QtGui>
 | 
			
		||||
 | 
			
		||||
#include <components/esm/esmreader.hpp>
 | 
			
		||||
#include <components/files/configurationmanager.hpp>
 | 
			
		||||
 | 
			
		||||
#include "model/datafilesmodel.hpp"
 | 
			
		||||
#include "model/esm/esmfile.hpp"
 | 
			
		||||
 | 
			
		||||
#include "utils/filedialog.hpp"
 | 
			
		||||
#include "utils/lineedit.hpp"
 | 
			
		||||
#include "utils/naturalsort.hpp"
 | 
			
		||||
 | 
			
		||||
#include "datafileslist.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/version.hpp>
 | 
			
		||||
/**
 | 
			
		||||
 * Workaround for problems with whitespaces in paths in older versions of Boost library
 | 
			
		||||
 */
 | 
			
		||||
#if (BOOST_VERSION <= 104600)
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    template<>
 | 
			
		||||
    inline boost::filesystem::path lexical_cast<boost::filesystem::path, std::string>(const std::string& arg)
 | 
			
		||||
    {
 | 
			
		||||
        return boost::filesystem::path(arg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
} /* namespace boost */
 | 
			
		||||
#endif /* (BOOST_VERSION <= 104600) */
 | 
			
		||||
 | 
			
		||||
using namespace ESM;
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
//sort QModelIndexList ascending
 | 
			
		||||
bool rowGreaterThan(const QModelIndex &index1, const QModelIndex &index2)
 | 
			
		||||
{
 | 
			
		||||
    return index1.row() >= index2.row();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//sort QModelIndexList descending
 | 
			
		||||
bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2)
 | 
			
		||||
{
 | 
			
		||||
    return index1.row() <= index2.row();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent)
 | 
			
		||||
    : QWidget(parent)
 | 
			
		||||
    , mCfgMgr(cfg)
 | 
			
		||||
{
 | 
			
		||||
    // Models
 | 
			
		||||
    mMastersModel = new DataFilesModel(this);
 | 
			
		||||
    mPluginsModel = new DataFilesModel(this);
 | 
			
		||||
 | 
			
		||||
    mPluginsProxyModel = new QSortFilterProxyModel();
 | 
			
		||||
    mPluginsProxyModel->setDynamicSortFilter(true);
 | 
			
		||||
    mPluginsProxyModel->setSourceModel(mPluginsModel);
 | 
			
		||||
 | 
			
		||||
    // Filter toolbar
 | 
			
		||||
    QLabel *filterLabel = new QLabel(tr("&Filter:"), this);
 | 
			
		||||
    LineEdit *filterLineEdit = new LineEdit(this);
 | 
			
		||||
    filterLabel->setBuddy(filterLineEdit);
 | 
			
		||||
 | 
			
		||||
    QToolBar *filterToolBar = new QToolBar(this);
 | 
			
		||||
    filterToolBar->setMovable(false);
 | 
			
		||||
 | 
			
		||||
    // Create a container widget and a layout to get the spacer to work
 | 
			
		||||
    QWidget *filterWidget = new QWidget(this);
 | 
			
		||||
    QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget);
 | 
			
		||||
    QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
 | 
			
		||||
 | 
			
		||||
    filterLayout->addItem(hSpacer1);
 | 
			
		||||
    filterLayout->addWidget(filterLabel);
 | 
			
		||||
    filterLayout->addWidget(filterLineEdit);
 | 
			
		||||
 | 
			
		||||
    filterToolBar->addWidget(filterWidget);
 | 
			
		||||
 | 
			
		||||
    QCheckBox checkBox;
 | 
			
		||||
    unsigned int height = checkBox.sizeHint().height() + 4;
 | 
			
		||||
 | 
			
		||||
    mMastersTable = new QTableView(this);
 | 
			
		||||
    mMastersTable->setModel(mMastersModel);
 | 
			
		||||
    mMastersTable->setObjectName("MastersTable");
 | 
			
		||||
    mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
 | 
			
		||||
    mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection);
 | 
			
		||||
    mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
 | 
			
		||||
    mMastersTable->setAlternatingRowColors(true);
 | 
			
		||||
    mMastersTable->horizontalHeader()->setStretchLastSection(true);
 | 
			
		||||
    mMastersTable->horizontalHeader()->hide();
 | 
			
		||||
 | 
			
		||||
    // Set the row height to the size of the checkboxes
 | 
			
		||||
    mMastersTable->verticalHeader()->setDefaultSectionSize(height);
 | 
			
		||||
    mMastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
 | 
			
		||||
    mMastersTable->verticalHeader()->hide();
 | 
			
		||||
    mMastersTable->setColumnHidden(1, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(2, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(3, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(4, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(5, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(6, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(7, true);
 | 
			
		||||
    mMastersTable->setColumnHidden(8, true);
 | 
			
		||||
 | 
			
		||||
    mPluginsTable = new QTableView(this);
 | 
			
		||||
    mPluginsTable->setModel(mPluginsProxyModel);
 | 
			
		||||
    mPluginsTable->setObjectName("PluginsTable");
 | 
			
		||||
    mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu);
 | 
			
		||||
    mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
 | 
			
		||||
    mPluginsTable->setSelectionMode(QAbstractItemView::SingleSelection);
 | 
			
		||||
    mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
 | 
			
		||||
    mPluginsTable->setAlternatingRowColors(true);
 | 
			
		||||
    mPluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
 | 
			
		||||
    mPluginsTable->horizontalHeader()->setStretchLastSection(true);
 | 
			
		||||
    mPluginsTable->horizontalHeader()->hide();
 | 
			
		||||
 | 
			
		||||
    mPluginsTable->verticalHeader()->setDefaultSectionSize(height);
 | 
			
		||||
    mPluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed);
 | 
			
		||||
    mPluginsTable->setColumnHidden(1, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(2, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(3, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(4, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(5, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(6, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(7, true);
 | 
			
		||||
    mPluginsTable->setColumnHidden(8, true);
 | 
			
		||||
 | 
			
		||||
    // Add both tables to a splitter
 | 
			
		||||
    QSplitter *splitter = new QSplitter(this);
 | 
			
		||||
    splitter->setOrientation(Qt::Horizontal);
 | 
			
		||||
    splitter->addWidget(mMastersTable);
 | 
			
		||||
    splitter->addWidget(mPluginsTable);
 | 
			
		||||
 | 
			
		||||
    // Adjust the default widget widths inside the splitter
 | 
			
		||||
    QList<int> sizeList;
 | 
			
		||||
    sizeList << 175 << 200;
 | 
			
		||||
    splitter->setSizes(sizeList);
 | 
			
		||||
 | 
			
		||||
    QVBoxLayout *pageLayout = new QVBoxLayout(this);
 | 
			
		||||
 | 
			
		||||
    pageLayout->addWidget(filterToolBar);
 | 
			
		||||
    pageLayout->addWidget(splitter);
 | 
			
		||||
 | 
			
		||||
    connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
 | 
			
		||||
    connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex)));
 | 
			
		||||
 | 
			
		||||
    connect(mMastersModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList)));
 | 
			
		||||
 | 
			
		||||
    connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString)));
 | 
			
		||||
 | 
			
		||||
    connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
 | 
			
		||||
 | 
			
		||||
    createActions();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::createActions()
 | 
			
		||||
{
 | 
			
		||||
    // Refresh the plugins
 | 
			
		||||
    QAction *refreshAction = new QAction(tr("Refresh"), this);
 | 
			
		||||
    refreshAction->setShortcut(QKeySequence(tr("F5")));
 | 
			
		||||
    connect(refreshAction, SIGNAL(triggered()), this, SLOT(refresh()));
 | 
			
		||||
 | 
			
		||||
    // Context menu actions
 | 
			
		||||
    mCheckAction = new QAction(tr("Check selected"), this);
 | 
			
		||||
    connect(mCheckAction, SIGNAL(triggered()), this, SLOT(check()));
 | 
			
		||||
 | 
			
		||||
    mUncheckAction = new QAction(tr("Uncheck selected"), this);
 | 
			
		||||
    connect(mUncheckAction, SIGNAL(triggered()), this, SLOT(uncheck()));
 | 
			
		||||
 | 
			
		||||
    // Context menu for the plugins table
 | 
			
		||||
    mContextMenu = new QMenu(this);
 | 
			
		||||
 | 
			
		||||
    mContextMenu->addAction(mCheckAction);
 | 
			
		||||
    mContextMenu->addAction(mUncheckAction);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString encoding)
 | 
			
		||||
{
 | 
			
		||||
    // Set the charset for reading the esm/esp files
 | 
			
		||||
    if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) {
 | 
			
		||||
        mMastersModel->setEncoding(encoding);
 | 
			
		||||
        mPluginsModel->setEncoding(encoding);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Add the paths to the respective models
 | 
			
		||||
    for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) {
 | 
			
		||||
        QString path = QString::fromStdString(it->string());
 | 
			
		||||
        path.remove(QChar('\"'));
 | 
			
		||||
        mMastersModel->addMasters(path);
 | 
			
		||||
        mPluginsModel->addPlugins(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mMastersModel->sort(0);
 | 
			
		||||
    mPluginsModel->sort(0);
 | 
			
		||||
//    mMastersTable->sortByColumn(3, Qt::AscendingOrder);
 | 
			
		||||
//    mPluginsTable->sortByColumn(3, Qt::AscendingOrder);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::selectedFiles(std::vector<boost::filesystem::path>& paths)
 | 
			
		||||
{
 | 
			
		||||
    QStringList masterPaths = mMastersModel->checkedItemsPaths();
 | 
			
		||||
    foreach (const QString &path, masterPaths)
 | 
			
		||||
    {
 | 
			
		||||
        paths.push_back(path.toStdString());
 | 
			
		||||
    }
 | 
			
		||||
    QStringList pluginPaths = mPluginsModel->checkedItemsPaths();
 | 
			
		||||
    foreach (const QString &path, pluginPaths)
 | 
			
		||||
    {
 | 
			
		||||
        paths.push_back(path.toStdString());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::check()
 | 
			
		||||
{
 | 
			
		||||
    // Check the current selection
 | 
			
		||||
    if (!mPluginsTable->selectionModel()->hasSelection()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes();
 | 
			
		||||
 | 
			
		||||
    //sort selection ascending because selectedIndexes returns an unsorted list
 | 
			
		||||
    //qSort(indexes.begin(), indexes.end(), rowSmallerThan);
 | 
			
		||||
 | 
			
		||||
    foreach (const QModelIndex &index, indexes) {
 | 
			
		||||
        if (!index.isValid())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        mPluginsModel->setCheckState(index, Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::uncheck()
 | 
			
		||||
{
 | 
			
		||||
    // uncheck the current selection
 | 
			
		||||
    if (!mPluginsTable->selectionModel()->hasSelection()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes();
 | 
			
		||||
 | 
			
		||||
    //sort selection ascending because selectedIndexes returns an unsorted list
 | 
			
		||||
    //qSort(indexes.begin(), indexes.end(), rowSmallerThan);
 | 
			
		||||
 | 
			
		||||
    foreach (const QModelIndex &index, indexes) {
 | 
			
		||||
        if (!index.isValid())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        mPluginsModel->setCheckState(index, Qt::Unchecked);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::refresh()
 | 
			
		||||
{
 | 
			
		||||
    mPluginsModel->sort(0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Refresh the plugins table
 | 
			
		||||
    mPluginsTable->scrollToTop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void DataFilesList::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(index);
 | 
			
		||||
 | 
			
		||||
        (mPluginsModel->checkState(sourceIndex) == Qt::Checked)
 | 
			
		||||
                ? mPluginsModel->setCheckState(sourceIndex, Qt::Unchecked)
 | 
			
		||||
                : mPluginsModel->setCheckState(sourceIndex, Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (object->objectName() == QLatin1String("MastersTable")) {
 | 
			
		||||
        (mMastersModel->checkState(index) == Qt::Checked)
 | 
			
		||||
                ? mMastersModel->setCheckState(index, Qt::Unchecked)
 | 
			
		||||
                : mMastersModel->setCheckState(index, Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::uncheckAll()
 | 
			
		||||
{
 | 
			
		||||
    mMastersModel->uncheckAll();
 | 
			
		||||
    mPluginsModel->uncheckAll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::filterChanged(const QString filter)
 | 
			
		||||
{
 | 
			
		||||
    QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString);
 | 
			
		||||
    mPluginsProxyModel->setFilterRegExp(regExp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::showContextMenu(const QPoint &point)
 | 
			
		||||
{
 | 
			
		||||
    // Make sure there are plugins in the view
 | 
			
		||||
    if (!mPluginsTable->selectionModel()->hasSelection()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QPoint globalPos = mPluginsTable->mapToGlobal(point);
 | 
			
		||||
 | 
			
		||||
    QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes();
 | 
			
		||||
 | 
			
		||||
    // Show the check/uncheck actions depending on the state of the selected items
 | 
			
		||||
    mUncheckAction->setEnabled(false);
 | 
			
		||||
    mCheckAction->setEnabled(false);
 | 
			
		||||
 | 
			
		||||
    foreach (const QModelIndex &index, indexes) {
 | 
			
		||||
        if (!index.isValid())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
         (mPluginsModel->checkState(index) == Qt::Checked)
 | 
			
		||||
             ? mUncheckAction->setEnabled(true)
 | 
			
		||||
             : mCheckAction->setEnabled(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Show menu
 | 
			
		||||
    mContextMenu->exec(globalPos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesList::setCheckState(const QString& element, Qt::CheckState state)
 | 
			
		||||
{
 | 
			
		||||
    EsmFile *file = mPluginsModel->findItem(element);
 | 
			
		||||
    if (file)
 | 
			
		||||
    {
 | 
			
		||||
        mPluginsModel->setCheckState(mPluginsModel->indexFromItem(file), Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        file = mMastersModel->findItem(element);
 | 
			
		||||
        mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList DataFilesList::checkedFiles()
 | 
			
		||||
{
 | 
			
		||||
    return mMastersModel->checkedItems() + mPluginsModel->checkedItems();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								components/fileorderlist/datafileslist.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								components/fileorderlist/datafileslist.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
#ifndef DATAFILESLIST_H
 | 
			
		||||
#define DATAFILESLIST_H
 | 
			
		||||
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
#include <QModelIndex>
 | 
			
		||||
#include <components/files/collections.hpp>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class QTableView;
 | 
			
		||||
class QSortFilterProxyModel;
 | 
			
		||||
class QSettings;
 | 
			
		||||
class QAction;
 | 
			
		||||
class QToolBar;
 | 
			
		||||
class QMenu;
 | 
			
		||||
class ProfilesComboBox;
 | 
			
		||||
class DataFilesModel;
 | 
			
		||||
 | 
			
		||||
class TextInputDialog;
 | 
			
		||||
 | 
			
		||||
namespace Files { struct ConfigurationManager; }
 | 
			
		||||
 | 
			
		||||
class DataFilesList : public QWidget
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    DataFilesList(Files::ConfigurationManager& cfg, QWidget *parent = 0);
 | 
			
		||||
 | 
			
		||||
    bool setupDataFiles(Files::PathContainer dataDirs, const QString encoding);
 | 
			
		||||
    void selectedFiles(std::vector<boost::filesystem::path>& paths);
 | 
			
		||||
    void uncheckAll();
 | 
			
		||||
    QStringList checkedFiles();
 | 
			
		||||
    void setCheckState(const QString& element, Qt::CheckState);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
    void setCheckState(QModelIndex index);
 | 
			
		||||
 | 
			
		||||
    void filterChanged(const QString filter);
 | 
			
		||||
    void showContextMenu(const QPoint &point);
 | 
			
		||||
 | 
			
		||||
    // Action slots
 | 
			
		||||
//    void moveUp();
 | 
			
		||||
//    void moveDown();
 | 
			
		||||
//    void moveTop();
 | 
			
		||||
//    void moveBottom();
 | 
			
		||||
    void check();
 | 
			
		||||
    void uncheck();
 | 
			
		||||
    void refresh();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    DataFilesModel *mMastersModel;
 | 
			
		||||
    DataFilesModel *mPluginsModel;
 | 
			
		||||
 | 
			
		||||
    QSortFilterProxyModel *mPluginsProxyModel;
 | 
			
		||||
 | 
			
		||||
    QTableView *mMastersTable;
 | 
			
		||||
    QTableView *mPluginsTable;
 | 
			
		||||
 | 
			
		||||
    QMenu *mContextMenu;
 | 
			
		||||
 | 
			
		||||
//    QAction *mMoveUpAction;
 | 
			
		||||
//    QAction *mMoveDownAction;
 | 
			
		||||
//    QAction *mMoveTopAction;
 | 
			
		||||
//    QAction *mMoveBottomAction;
 | 
			
		||||
    QAction *mCheckAction;
 | 
			
		||||
    QAction *mUncheckAction;
 | 
			
		||||
 | 
			
		||||
    Files::ConfigurationManager &mCfgMgr;
 | 
			
		||||
 | 
			
		||||
//    const QStringList checkedPlugins();
 | 
			
		||||
//    const QStringList selectedMasters();
 | 
			
		||||
 | 
			
		||||
    void createActions();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -292,6 +292,7 @@ void DataFilesModel::addMasters(const QString &path)
 | 
			
		|||
 | 
			
		||||
                EsmFile *file = new EsmFile(master);
 | 
			
		||||
                file->setDates(info.lastModified(), info.lastRead());
 | 
			
		||||
                file->setPath(info.absoluteFilePath());
 | 
			
		||||
 | 
			
		||||
                // Add the master to the table
 | 
			
		||||
                if (findItem(master) == 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -427,6 +428,25 @@ QStringList DataFilesModel::checkedItems()
 | 
			
		|||
    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 && mAvailableFiles.contains(file->fileName()))
 | 
			
		||||
            list << file->path();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DataFilesModel::uncheckAll()
 | 
			
		||||
{
 | 
			
		||||
    emit layoutAboutToBeChanged();
 | 
			
		||||
| 
						 | 
				
			
			@ -43,6 +43,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    QStringList checkedItems();
 | 
			
		||||
    QStringList uncheckedItems();
 | 
			
		||||
    QStringList checkedItemsPaths();
 | 
			
		||||
 | 
			
		||||
    Qt::CheckState checkState(const QModelIndex &index);
 | 
			
		||||
    void setCheckState(const QModelIndex &index, Qt::CheckState state);
 | 
			
		||||
		Loading…
	
		Reference in a new issue