Merge branch 'regionmap'

actorid
Marc Zinnschlag 11 years ago
commit 71068ae3ad

@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
scenetoolmode infocreator scriptedit dialoguesubview previewsubview
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap
)
opencs_units (view/render

@ -9,6 +9,9 @@
namespace CSMWorld
{
/// \brief Wrapper for Cell record
///
/// \attention The mData.mX and mData.mY fields of the ESM::Cell struct are not used.
/// Exterior cell coordinates are encoded in the cell ID.
struct Cell : public ESM::Cell
{
std::string mId;

@ -1,6 +1,7 @@
#include "regionmap.hpp"
#include <cmath>
#include <algorithm>
#include <QBrush>
@ -25,17 +26,28 @@ CSMWorld::RegionMap::CellDescription::CellDescription (const Record<Cell>& cell)
mName = cell2.mName;
}
CSMWorld::RegionMap::CellIndex CSMWorld::RegionMap::getIndex (const QModelIndex& index) const
CSMWorld::CellCoordinates CSMWorld::RegionMap::getIndex (const QModelIndex& index) const
{
return CellIndex (index.column()+mMin.first,
(mMax.second-mMin.second - index.row()-1)+mMin.second);
return mMin.move (index.column(), mMax.getY()-mMin.getY() - index.row()-1);
}
QModelIndex CSMWorld::RegionMap::getIndex (const CellIndex& index) const
QModelIndex CSMWorld::RegionMap::getIndex (const CellCoordinates& index) const
{
// I hate you, Qt API naming scheme!
return QAbstractTableModel::index (mMax.second-mMin.second - (index.second-mMin.second)-1,
index.first-mMin.first);
return QAbstractTableModel::index (mMax.getY()-mMin.getY() - (index.getY()-mMin.getY())-1,
index.getX()-mMin.getX());
}
CSMWorld::CellCoordinates CSMWorld::RegionMap::getIndex (const Cell& cell) const
{
std::istringstream stream (cell.mId);
char ignore;
int x = 0;
int y = 0;
stream >> ignore >> x >> y;
return CellCoordinates (x, y);
}
void CSMWorld::RegionMap::buildRegions()
@ -70,21 +82,21 @@ void CSMWorld::RegionMap::buildMap()
{
CellDescription description (cell);
CellIndex index (cell2.mData.mX, cell2.mData.mY);
CellCoordinates index = getIndex (cell2);
mMap.insert (std::make_pair (index, description));
}
}
std::pair<CellIndex, CellIndex> mapSize = getSize();
std::pair<CellCoordinates, CellCoordinates> mapSize = getSize();
mMin = mapSize.first;
mMax = mapSize.second;
}
void CSMWorld::RegionMap::addCell (const CellIndex& index, const CellDescription& description)
void CSMWorld::RegionMap::addCell (const CellCoordinates& index, const CellDescription& description)
{
std::map<CellIndex, CellDescription>::iterator cell = mMap.find (index);
std::map<CellCoordinates, CellDescription>::iterator cell = mMap.find (index);
if (cell!=mMap.end())
{
@ -114,7 +126,7 @@ void CSMWorld::RegionMap::addCells (int start, int end)
if (cell2.isExterior())
{
CellIndex index (cell2.mData.mX, cell2.mData.mY);
CellCoordinates index = getIndex (cell2);
CellDescription description (cell);
@ -123,9 +135,9 @@ void CSMWorld::RegionMap::addCells (int start, int end)
}
}
void CSMWorld::RegionMap::removeCell (const CellIndex& index)
void CSMWorld::RegionMap::removeCell (const CellCoordinates& index)
{
std::map<CellIndex, CellDescription>::iterator cell = mMap.find (index);
std::map<CellCoordinates, CellDescription>::iterator cell = mMap.find (index);
if (cell!=mMap.end())
{
@ -160,7 +172,7 @@ void CSMWorld::RegionMap::updateRegions (const std::vector<std::string>& regions
std::for_each (regions2.begin(), regions2.end(), &Misc::StringUtils::lowerCase);
std::sort (regions2.begin(), regions2.end());
for (std::map<CellIndex, CellDescription>::const_iterator iter (mMap.begin());
for (std::map<CellCoordinates, CellDescription>::const_iterator iter (mMap.begin());
iter!=mMap.end(); ++iter)
{
if (!iter->second.mRegion.empty() &&
@ -176,90 +188,57 @@ void CSMWorld::RegionMap::updateRegions (const std::vector<std::string>& regions
void CSMWorld::RegionMap::updateSize()
{
std::pair<CellIndex, CellIndex> size = getSize();
std::pair<CellCoordinates, CellCoordinates> size = getSize();
if (int diff = size.first.getX() - mMin.getX())
{
int diff = size.first.first - mMin.first;
if (diff<0)
{
beginInsertColumns (QModelIndex(), 0, -diff-1);
mMin.first = size.first.first;
endInsertColumns();
}
else if (diff>0)
{
beginRemoveColumns (QModelIndex(), 0, diff-1);
mMin.first = size.first.first;
endRemoveColumns();
}
beginInsertColumns (QModelIndex(), 0, std::abs (diff)-1);
mMin = CellCoordinates (size.first.getX(), mMin.getY());
endInsertColumns();
}
if (int diff = size.first.getY() - mMin.getY())
{
int diff = size.first.second - mMin.second;
if (diff<0)
{
beginInsertRows (QModelIndex(), 0, -diff-1);
mMin.second = size.first.second;
endInsertRows();
}
else if (diff>0)
{
beginRemoveRows (QModelIndex(), 0, diff-1);
mMin.second = size.first.second;
endRemoveRows();
}
beginInsertRows (QModelIndex(), 0, std::abs (diff)-1);
mMin = CellCoordinates (mMin.getX(), size.first.getY());
endInsertRows();
}
if (int diff = size.second.getX() - mMax.getX())
{
int diff = size.second.first - mMax.first;
int columns = columnCount();
if (diff>0)
{
int columns = columnCount();
beginInsertColumns (QModelIndex(), columns, columns+diff-1);
mMax.first = size.second.first;
endInsertColumns();
}
else if (diff<0)
{
int columns = columnCount();
else
beginRemoveColumns (QModelIndex(), columns+diff, columns-1);
mMax.first = size.second.first;
endRemoveColumns();
}
mMax = CellCoordinates (size.second.getX(), mMax.getY());
endInsertColumns();
}
if (int diff = size.second.getY() - mMax.getY())
{
int diff = size.second.second - mMax.second;
int rows = rowCount();
if (diff>0)
{
int rows = rowCount();
beginInsertRows (QModelIndex(), rows, rows+diff-1);
mMax.second = size.second.second;
endInsertRows();
}
else if (diff<0)
{
int rows = rowCount();
else
beginRemoveRows (QModelIndex(), rows+diff, rows-1);
mMax.second = size.second.second;
endRemoveRows();
}
mMax = CellCoordinates (mMax.getX(), size.second.getY());
endInsertRows();
}
}
std::pair<CSMWorld::RegionMap::CellIndex, CSMWorld::RegionMap::CellIndex> CSMWorld::RegionMap::getSize()
const
std::pair<CSMWorld::CellCoordinates, CSMWorld::CellCoordinates> CSMWorld::RegionMap::getSize() const
{
const IdCollection<Cell>& cells = mData.getCells();
int size = cells.getSize();
CellIndex min (0, 0);
CellIndex max (0, 0);
CellCoordinates min (0, 0);
CellCoordinates max (0, 0);
for (int i=0; i<size; ++i)
{
@ -269,24 +248,24 @@ std::pair<CSMWorld::RegionMap::CellIndex, CSMWorld::RegionMap::CellIndex> CSMWor
if (cell2.isExterior())
{
CellIndex index (cell2.mData.mX, cell2.mData.mY);
CellCoordinates index = getIndex (cell2);
if (min==max)
{
min = index;
max = std::make_pair (min.first+1, min.second+1);
max = min.move (1, 1);
}
else
{
if (index.first<min.first)
min.first = index.first;
else if (index.first>=max.first)
max.first = index.first + 1;
if (index.second<min.second)
min.second = index.second;
else if (index.second>=max.second)
max.second = index.second + 1;
if (index.getX()<min.getX())
min = CellCoordinates (index.getX(), min.getY());
else if (index.getX()>=max.getX())
max = CellCoordinates (index.getX()+1, max.getY());
if (index.getY()<min.getY())
min = CellCoordinates (min.getX(), index.getY());
else if (index.getY()>=max.getY())
max = CellCoordinates (max.getX(), index.getY() + 1);
}
}
}
@ -323,7 +302,7 @@ int CSMWorld::RegionMap::rowCount (const QModelIndex& parent) const
if (parent.isValid())
return 0;
return mMax.second-mMin.second;
return mMax.getY()-mMin.getY();
}
int CSMWorld::RegionMap::columnCount (const QModelIndex& parent) const
@ -331,7 +310,7 @@ int CSMWorld::RegionMap::columnCount (const QModelIndex& parent) const
if (parent.isValid())
return 0;
return mMax.first-mMin.first;
return mMax.getX()-mMin.getX();
}
QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
@ -343,7 +322,7 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
{
/// \todo GUI class in non-GUI code. Needs to be addressed eventually.
std::map<CellIndex, CellDescription>::const_iterator cell =
std::map<CellCoordinates, CellDescription>::const_iterator cell =
mMap.find (getIndex (index));
if (cell!=mMap.end())
@ -370,13 +349,13 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
if (role==Qt::ToolTipRole)
{
CellIndex cellIndex = getIndex (index);
CellCoordinates cellIndex = getIndex (index);
std::ostringstream stream;
stream << cellIndex.first << ", " << cellIndex.second;
stream << cellIndex;
std::map<CellIndex, CellDescription>::const_iterator cell =
std::map<CellCoordinates, CellDescription>::const_iterator cell =
mMap.find (cellIndex);
if (cell!=mMap.end())
@ -406,15 +385,33 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
return QString::fromUtf8 (stream.str().c_str());
}
if (role==Role_Region)
{
CellCoordinates cellIndex = getIndex (index);
std::map<CellCoordinates, CellDescription>::const_iterator cell =
mMap.find (cellIndex);
if (cell!=mMap.end() && !cell->second.mRegion.empty())
return QString::fromUtf8 (Misc::StringUtils::lowerCase (cell->second.mRegion).c_str());
}
if (role==Role_CellId)
{
CellCoordinates cellIndex = getIndex (index);
std::ostringstream stream;
stream << "#" << cellIndex.getX() << " " << cellIndex.getY();
return QString::fromUtf8 (stream.str().c_str());
}
return QVariant();
}
Qt::ItemFlags CSMWorld::RegionMap::flags (const QModelIndex& index) const
{
if (mMap.find (getIndex (index))!=mMap.end())
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return 0;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
void CSMWorld::RegionMap::regionsAboutToBeRemoved (const QModelIndex& parent, int start, int end)
@ -491,11 +488,7 @@ void CSMWorld::RegionMap::cellsAboutToBeRemoved (const QModelIndex& parent, int
const Cell& cell2 = cell.get();
if (cell2.isExterior())
{
CellIndex index (cell2.mData.mX, cell2.mData.mY);
removeCell (index);
}
removeCell (getIndex (cell2));
}
}

@ -9,6 +9,7 @@
#include "record.hpp"
#include "cell.hpp"
#include "cellcoordinates.hpp"
namespace CSMWorld
{
@ -23,7 +24,11 @@ namespace CSMWorld
public:
typedef std::pair<int, int> CellIndex;
enum Role
{
Role_Region = Qt::UserRole,
Role_CellId = Qt::UserRole+1
};
private:
@ -39,27 +44,29 @@ namespace CSMWorld
};
Data& mData;
std::map<CellIndex, CellDescription> mMap;
CellIndex mMin; ///< inclusive
CellIndex mMax; ///< exclusive
std::map<CellCoordinates, CellDescription> mMap;
CellCoordinates mMin; ///< inclusive
CellCoordinates mMax; ///< exclusive
std::map<std::string, unsigned int> mColours; ///< region ID, colour (RGBA)
CellIndex getIndex (const QModelIndex& index) const;
CellCoordinates getIndex (const QModelIndex& index) const;
///< Translates a Qt model index into a cell index (which can contain negative components)
QModelIndex getIndex (const CellIndex& index) const;
QModelIndex getIndex (const CellCoordinates& index) const;
CellCoordinates getIndex (const Cell& cell) const;
void buildRegions();
void buildMap();
void addCell (const CellIndex& index, const CellDescription& description);
void addCell (const CellCoordinates& index, const CellDescription& description);
///< May be called on a cell that is already in the map (in which case an update is
// performed)
void addCells (int start, int end);
void removeCell (const CellIndex& index);
void removeCell (const CellCoordinates& index);
///< May be called on a cell that is not in the map (in which case the call is ignored)
void addRegion (const std::string& region, unsigned int colour);
@ -78,7 +85,7 @@ namespace CSMWorld
void updateSize();
std::pair<CellIndex, CellIndex> getSize() const;
std::pair<CellCoordinates, CellCoordinates> getSize() const;
public:
@ -89,6 +96,8 @@ namespace CSMWorld
virtual int columnCount (const QModelIndex& parent = QModelIndex()) const;
virtual QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) const;
///< \note Calling this function with role==Role_CellId may return the ID of a cell
/// that does not exist.
virtual Qt::ItemFlags flags (const QModelIndex& index) const;

@ -15,23 +15,28 @@ CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent)
layout->setContentsMargins (0, 0, 0, 0);
RecordFilterBox *recordFilterBox = new RecordFilterBox (data, this);
mRecordFilterBox = new RecordFilterBox (data, this);
layout->addWidget (recordFilterBox);
layout->addWidget (mRecordFilterBox);
setLayout (layout);
connect (recordFilterBox,
connect (mRecordFilterBox,
SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
recordFilterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
mRecordFilterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), recordFilterBox, SIGNAL(useFilterRequest(const std::string&)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), mRecordFilterBox, SIGNAL(useFilterRequest(const std::string&)));
setAcceptDrops(true);
}
void CSVFilter::FilterBox::setRecordFilter (const std::string& filter)
{
mRecordFilterBox->setFilter (filter);
}
void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
{
std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData();

@ -16,10 +16,14 @@ namespace CSMWorld
namespace CSVFilter
{
class RecordFilterBox;
class FilterBox : public QWidget
{
Q_OBJECT
RecordFilterBox *mRecordFilterBox;
void dragEnterEvent (QDragEnterEvent* event);
void dropEvent (QDropEvent* event);
@ -30,11 +34,13 @@ namespace CSVFilter
FilterBox (CSMWorld::Data& data, QWidget *parent = 0);
void setRecordFilter (const std::string& filter);
signals:
void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter);
void recordDropped (std::vector<CSMWorld::UniversalId>& types, Qt::DropAction action);
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
void createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >& filterSource,
Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter);
};

@ -15,18 +15,23 @@ CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *pare
layout->addWidget (new QLabel ("Record Filter", this));
EditWidget *editWidget = new EditWidget (data, this);
mEdit = new EditWidget (data, this);
layout->addWidget (editWidget);
layout->addWidget (mEdit);
setLayout (layout);
connect (
editWidget, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
mEdit, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
editWidget, SLOT(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
mEdit, SLOT(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), editWidget, SLOT(useFilterRequest(const std::string&)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), mEdit, SLOT(useFilterRequest(const std::string&)));
}
void CSVFilter::RecordFilterBox::setFilter (const std::string& filter)
{
mEdit->setText (QString::fromUtf8 (filter.c_str()));
}

@ -17,14 +17,20 @@ namespace CSMWorld
namespace CSVFilter
{
class EditWidget;
class RecordFilterBox : public QWidget
{
Q_OBJECT
EditWidget *mEdit;
public:
RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0);
void setFilter (const std::string& filter);
signals:
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter);

@ -0,0 +1,346 @@
#include "regionmap.hpp"
#include <algorithm>
#include <set>
#include <sstream>
#include <QHeaderView>
#include <QContextMenuEvent>
#include <QMenu>
#include "../../model/doc/document.hpp"
#include "../../model/world/regionmap.hpp"
#include "../../model/world/universalid.hpp"
#include "../../model/world/data.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/columns.hpp"
void CSVWorld::RegionMap::contextMenuEvent (QContextMenuEvent *event)
{
QMenu menu (this);
if (getUnselectedCells().size()>0)
menu.addAction (mSelectAllAction);
if (selectionModel()->selectedIndexes().size()>0)
menu.addAction (mClearSelectionAction);
if (getMissingRegionCells().size()>0)
menu.addAction (mSelectRegionsAction);
int selectedNonExistentCells = getSelectedCells (false, true).size();
if (selectedNonExistentCells>0)
{
if (selectedNonExistentCells==1)
mCreateCellsAction->setText ("Create one Cell");
else
{
std::ostringstream stream;
stream << "Create " << selectedNonExistentCells << " cells";
mCreateCellsAction->setText (QString::fromUtf8 (stream.str().c_str()));
}
menu.addAction (mCreateCellsAction);
}
if (getSelectedCells().size()>0)
{
if (!mRegionId.empty())
{
mSetRegionAction->setText (QString::fromUtf8 (("Set Region to " + mRegionId).c_str()));
menu.addAction (mSetRegionAction);
}
menu.addAction (mUnsetRegionAction);
menu.addAction (mViewInTableAction);
}
if (selectionModel()->selectedIndexes().size()>0)
menu.addAction (mViewAction);
menu.exec (event->globalPos());
}
QModelIndexList CSVWorld::RegionMap::getUnselectedCells() const
{
const QAbstractItemModel *model = QTableView::model();
int rows = model->rowCount();
int columns = model->columnCount();
QModelIndexList selected = selectionModel()->selectedIndexes();
std::sort (selected.begin(), selected.end());
QModelIndexList all;
for (int y=0; y<rows; ++y)
for (int x=0; x<columns; ++x)
{
QModelIndex index = model->index (y, x);
if (model->data (index, Qt::BackgroundRole)!=QBrush (Qt::DiagCrossPattern))
all.push_back (index);
}
std::sort (all.begin(), all.end());
QModelIndexList list;
std::set_difference (all.begin(), all.end(), selected.begin(), selected.end(),
std::back_inserter (list));
return list;
}
QModelIndexList CSVWorld::RegionMap::getSelectedCells (bool existent, bool nonExistent) const
{
const QAbstractItemModel *model = QTableView::model();
QModelIndexList selected = selectionModel()->selectedIndexes();
QModelIndexList list;
for (QModelIndexList::const_iterator iter (selected.begin()); iter!=selected.end(); ++iter)
{
bool exists = model->data (*iter, Qt::BackgroundRole)!=QBrush (Qt::DiagCrossPattern);
if ((exists && existent) || (!exists && nonExistent))
list.push_back (*iter);
}
return list;
}
QModelIndexList CSVWorld::RegionMap::getMissingRegionCells() const
{
const QAbstractItemModel *model = QTableView::model();
QModelIndexList selected = selectionModel()->selectedIndexes();
std::set<std::string> regions;
for (QModelIndexList::const_iterator iter (selected.begin()); iter!=selected.end(); ++iter)
{
std::string region =
model->data (*iter, CSMWorld::RegionMap::Role_Region).toString().toUtf8().constData();
if (!region.empty())
regions.insert (region);
}
QModelIndexList list;
QModelIndexList unselected = getUnselectedCells();
for (QModelIndexList::const_iterator iter (unselected.begin()); iter!=unselected.end(); ++iter)
{
std::string region =
model->data (*iter, CSMWorld::RegionMap::Role_Region).toString().toUtf8().constData();
if (!region.empty() && regions.find (region)!=regions.end())
list.push_back (*iter);
}
return list;
}
void CSVWorld::RegionMap::setRegion (const std::string& regionId)
{
QModelIndexList selected = getSelectedCells();
QAbstractItemModel *regionModel = model();
CSMWorld::IdTable *cellsModel = &dynamic_cast<CSMWorld::IdTable&> (*
mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
QString regionId2 = QString::fromUtf8 (regionId.c_str());
if (selected.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Set Region"));
for (QModelIndexList::const_iterator iter (selected.begin()); iter!=selected.end(); ++iter)
{
std::string cellId = regionModel->data (*iter, CSMWorld::RegionMap::Role_CellId).
toString().toUtf8().constData();
QModelIndex index = cellsModel->getModelIndex (cellId,
cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region));
mDocument.getUndoStack().push (
new CSMWorld::ModifyCommand (*cellsModel, index, regionId2));
}
if (selected.size()>1)
mDocument.getUndoStack().endMacro();
}
CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId,
CSMDoc::Document& document, QWidget *parent)
: QTableView (parent), mEditLock (false), mDocument (document)
{
verticalHeader()->hide();
horizontalHeader()->hide();
setSelectionMode (QAbstractItemView::ExtendedSelection);
setModel (document.getData().getTableModel (universalId));
resizeColumnsToContents();
resizeRowsToContents();
mSelectAllAction = new QAction (tr ("Select All"), this);
connect (mSelectAllAction, SIGNAL (triggered()), this, SLOT (selectAll()));
addAction (mSelectAllAction);
mClearSelectionAction = new QAction (tr ("Clear Selection"), this);
connect (mClearSelectionAction, SIGNAL (triggered()), this, SLOT (clearSelection()));
addAction (mClearSelectionAction);
mSelectRegionsAction = new QAction (tr ("Select Regions"), this);
connect (mSelectRegionsAction, SIGNAL (triggered()), this, SLOT (selectRegions()));
addAction (mSelectRegionsAction);
mCreateCellsAction = new QAction (tr ("Create Cells Action"), this);
connect (mCreateCellsAction, SIGNAL (triggered()), this, SLOT (createCells()));
addAction (mCreateCellsAction);
mSetRegionAction = new QAction (tr ("Set Region"), this);
connect (mSetRegionAction, SIGNAL (triggered()), this, SLOT (setRegion()));
addAction (mSetRegionAction);
mUnsetRegionAction = new QAction (tr ("Unset Region"), this);
connect (mUnsetRegionAction, SIGNAL (triggered()), this, SLOT (unsetRegion()));
addAction (mUnsetRegionAction);
mViewAction = new QAction (tr ("View Cells"), this);
connect (mViewAction, SIGNAL (triggered()), this, SLOT (view()));
addAction (mViewAction);
mViewInTableAction = new QAction (tr ("View Cells in Table"), this);
connect (mViewInTableAction, SIGNAL (triggered()), this, SLOT (viewInTable()));
addAction (mViewInTableAction);
}
void CSVWorld::RegionMap::setEditLock (bool locked)
{
mEditLock = locked;
}
void CSVWorld::RegionMap::selectAll()
{
QModelIndexList unselected = getUnselectedCells();
for (QModelIndexList::const_iterator iter (unselected.begin()); iter!=unselected.end(); ++iter)
selectionModel()->select (*iter, QItemSelectionModel::Select);
}
void CSVWorld::RegionMap::clearSelection()
{
selectionModel()->clearSelection();
}
void CSVWorld::RegionMap::selectRegions()
{
QModelIndexList unselected = getMissingRegionCells();
for (QModelIndexList::const_iterator iter (unselected.begin()); iter!=unselected.end(); ++iter)
selectionModel()->select (*iter, QItemSelectionModel::Select);
}
void CSVWorld::RegionMap::createCells()
{
if (mEditLock)
return;
QModelIndexList selected = getSelectedCells (false, true);
CSMWorld::IdTable *cellsModel = &dynamic_cast<CSMWorld::IdTable&> (*
mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
if (selected.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Create cells"));
for (QModelIndexList::const_iterator iter (selected.begin()); iter!=selected.end(); ++iter)
{
std::string cellId = model()->data (*iter, CSMWorld::RegionMap::Role_CellId).
toString().toUtf8().constData();
mDocument.getUndoStack().push (new CSMWorld::CreateCommand (*cellsModel, cellId));
}
if (selected.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSVWorld::RegionMap::setRegion()
{
if (mEditLock)
return;
setRegion (mRegionId);
}
void CSVWorld::RegionMap::unsetRegion()
{
if (mEditLock)
return;
setRegion ("");
}
void CSVWorld::RegionMap::view()
{
std::ostringstream hint;
hint << "c:";
QModelIndexList selected = selectionModel()->selectedIndexes();
bool first = true;
for (QModelIndexList::const_iterator iter (selected.begin()); iter!=selected.end(); ++iter)
{
std::string cellId = model()->data (*iter, CSMWorld::RegionMap::Role_CellId).
toString().toUtf8().constData();
if (first)
first = false;
else
hint << "; ";
hint << cellId;
}
emit editRequest (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Scene, "sys::default"),
hint.str());
}
void CSVWorld::RegionMap::viewInTable()
{
std::ostringstream hint;
hint << "f:!or(";
QModelIndexList selected = getSelectedCells();
bool first = true;
for (QModelIndexList::const_iterator iter (selected.begin()); iter!=selected.end(); ++iter)
{
std::string cellId = model()->data (*iter, CSMWorld::RegionMap::Role_CellId).
toString().toUtf8().constData();
if (first)
first = false;
else
hint << ",";
hint << "string(ID,\"" << cellId << "\")";
}
hint << ")";
emit editRequest (CSMWorld::UniversalId::Type_Cells, hint.str());
}

@ -0,0 +1,84 @@
#ifndef CSV_WORLD_REGIONMAP_H
#define CSV_WORLD_REGIONMAP_H
#include <QTableView>
class QAction;
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
class UniversalId;
}
namespace CSVWorld
{
class RegionMap : public QTableView
{
Q_OBJECT
QAction *mSelectAllAction;
QAction *mClearSelectionAction;
QAction *mSelectRegionsAction;
QAction *mCreateCellsAction;
QAction *mSetRegionAction;
QAction *mUnsetRegionAction;
QAction *mViewAction;
QAction *mViewInTableAction;
bool mEditLock;
CSMDoc::Document& mDocument;
std::string mRegionId;
private:
void contextMenuEvent (QContextMenuEvent *event);
QModelIndexList getUnselectedCells() const;
///< \note Non-existent cells are not listed.
QModelIndexList getSelectedCells (bool existent = true, bool nonExistent = false) const;
///< \param existant Include existant cells.
/// \param nonExistant Include non-existant cells.
QModelIndexList getMissingRegionCells() const;
///< Unselected cells within all regions that have at least one selected cell.
void setRegion (const std::string& regionId);
///< Set region Id of selected cells.
public:
RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document,
QWidget *parent = 0);
void setEditLock (bool locked);
signals:
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
private slots:
void selectAll();
void clearSelection();
void selectRegions();
void createCells();
void setRegion();
void unsetRegion();
void view();
void viewInTable();
};
}
#endif

@ -1,29 +1,27 @@
#include "regionmapsubview.hpp"
#include <QTableView>
#include <QHeaderView>
#include "regionmap.hpp"
CSVWorld::RegionMapSubView::RegionMapSubView (CSMWorld::UniversalId universalId,
CSMDoc::Document& document)
: CSVDoc::SubView (universalId)
{
mTable = new QTableView (this);
mRegionMap = new RegionMap (universalId, document, this);
mTable->verticalHeader()->hide();
mTable->horizontalHeader()->hide();
setWidget (mRegionMap);
mTable->setSelectionMode (QAbstractItemView::ExtendedSelection);
mTable->setModel (document.getData().getTableModel (universalId));
mTable->resizeColumnsToContents();
mTable->resizeRowsToContents();
setWidget (mTable);
connect (mRegionMap, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)),
this, SLOT (editRequest (const CSMWorld::UniversalId&, const std::string&)));
}
void CSVWorld::RegionMapSubView::setEditLock (bool locked)
{
mRegionMap->setEditLock (locked);
}
void CSVWorld::RegionMapSubView::editRequest (const CSMWorld::UniversalId& id,
const std::string& hint)
{
focusId (id, hint);
}

@ -3,7 +3,7 @@
#include "../doc/subview.hpp"
class QTableView;
class QAction;
namespace CSMDoc
{
@ -12,15 +12,23 @@ namespace CSMDoc
namespace CSVWorld
{
class RegionMap;
class RegionMapSubView : public CSVDoc::SubView
{
QTableView *mTable;
Q_OBJECT
RegionMap *mRegionMap;
public:
RegionMapSubView (CSMWorld::UniversalId universalId, CSMDoc::Document& document);
virtual void setEditLock (bool locked);
private slots:
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
};
}

@ -358,6 +358,9 @@ void CSVWorld::Table::cloneRecord()
void CSVWorld::Table::moveUpRecord()
{
if (mEditLock)
return;
QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.size()==1)
@ -387,6 +390,9 @@ void CSVWorld::Table::moveUpRecord()
void CSVWorld::Table::moveDownRecord()
{
if (mEditLock)
return;
QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.size()==1)

@ -26,9 +26,9 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
layout->insertWidget (0, mTable =
new Table (id, mBottom->canCreateAndDelete(), sorting, document), 2);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
mFilterBox = new CSVFilter::FilterBox (document.getData(), this);
layout->insertWidget (0, filterBox);
layout->insertWidget (0, mFilterBox);
QWidget *widget = new QWidget;
@ -48,7 +48,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
mTable->selectionSizeUpdate();
mTable->viewport()->installEventFilter(this);
mBottom->installEventFilter(this);
filterBox->installEventFilter(this);
mFilterBox->installEventFilter(this);
if (mBottom->canCreateAndDelete())
{
@ -63,17 +63,17 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
connect (mBottom, SIGNAL (requestFocus (const std::string&)),
mTable, SLOT (requestFocus (const std::string&)));
connect (filterBox,
connect (mFilterBox,
SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)),
mTable, SLOT (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(filterBox, SIGNAL(recordDropped(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)),
connect(mFilterBox, SIGNAL(recordDropped(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)),
this, SLOT(createFilterRequest(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), filterBox, SIGNAL(useFilterRequest(const std::string&)));
connect(this, SIGNAL(useFilterRequest(const std::string&)), mFilterBox, SIGNAL(useFilterRequest(const std::string&)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)),
filterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
mFilterBox, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)));
}
void CSVWorld::TableSubView::setEditLock (bool locked)
@ -97,6 +97,15 @@ void CSVWorld::TableSubView::setStatusBar (bool show)
mBottom->setStatusBar (show);
}
void CSVWorld::TableSubView::useHint (const std::string& hint)
{
if (hint.empty())
return;
if (hint[0]=='f' && hint.size()>=2)
mFilterBox->setRecordFilter (hint.substr (2));
}
void CSVWorld::TableSubView::cloneRequest(const CSMWorld::UniversalId& toClone)
{
emit cloneRequest(toClone.getId(), toClone.getType());

@ -17,6 +17,11 @@ namespace CSMDoc
class Document;
}
namespace CSVFilter
{
class FilterBox;
}
namespace CSVWorld
{
class Table;
@ -29,6 +34,7 @@ namespace CSVWorld
Table *mTable;
TableBottomBox *mBottom;
CSVFilter::FilterBox *mFilterBox;
public:
@ -41,6 +47,8 @@ namespace CSVWorld
virtual void setStatusBar (bool show);
virtual void useHint (const std::string& hint);
protected:
bool eventFilter(QObject* object, QEvent *event);

Loading…
Cancel
Save