Merge branch 'regionmap'

actorid
Marc Zinnschlag 11 years ago
commit 71068ae3ad

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

@ -9,6 +9,9 @@
namespace CSMWorld namespace CSMWorld
{ {
/// \brief Wrapper for Cell record /// \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 struct Cell : public ESM::Cell
{ {
std::string mId; std::string mId;

@ -1,6 +1,7 @@
#include "regionmap.hpp" #include "regionmap.hpp"
#include <cmath>
#include <algorithm> #include <algorithm>
#include <QBrush> #include <QBrush>
@ -25,17 +26,28 @@ CSMWorld::RegionMap::CellDescription::CellDescription (const Record<Cell>& cell)
mName = cell2.mName; 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, return mMin.move (index.column(), mMax.getY()-mMin.getY() - index.row()-1);
(mMax.second-mMin.second - index.row()-1)+mMin.second);
} }
QModelIndex CSMWorld::RegionMap::getIndex (const CellIndex& index) const QModelIndex CSMWorld::RegionMap::getIndex (const CellCoordinates& index) const
{ {
// I hate you, Qt API naming scheme! // I hate you, Qt API naming scheme!
return QAbstractTableModel::index (mMax.second-mMin.second - (index.second-mMin.second)-1, return QAbstractTableModel::index (mMax.getY()-mMin.getY() - (index.getY()-mMin.getY())-1,
index.first-mMin.first); 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() void CSMWorld::RegionMap::buildRegions()
@ -70,21 +82,21 @@ void CSMWorld::RegionMap::buildMap()
{ {
CellDescription description (cell); CellDescription description (cell);
CellIndex index (cell2.mData.mX, cell2.mData.mY); CellCoordinates index = getIndex (cell2);
mMap.insert (std::make_pair (index, description)); mMap.insert (std::make_pair (index, description));
} }
} }
std::pair<CellIndex, CellIndex> mapSize = getSize(); std::pair<CellCoordinates, CellCoordinates> mapSize = getSize();
mMin = mapSize.first; mMin = mapSize.first;
mMax = mapSize.second; 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()) if (cell!=mMap.end())
{ {
@ -114,7 +126,7 @@ void CSMWorld::RegionMap::addCells (int start, int end)
if (cell2.isExterior()) if (cell2.isExterior())
{ {
CellIndex index (cell2.mData.mX, cell2.mData.mY); CellCoordinates index = getIndex (cell2);
CellDescription description (cell); 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()) 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::for_each (regions2.begin(), regions2.end(), &Misc::StringUtils::lowerCase);
std::sort (regions2.begin(), regions2.end()); 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) iter!=mMap.end(); ++iter)
{ {
if (!iter->second.mRegion.empty() && if (!iter->second.mRegion.empty() &&
@ -176,90 +188,57 @@ void CSMWorld::RegionMap::updateRegions (const std::vector<std::string>& regions
void CSMWorld::RegionMap::updateSize() 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; beginInsertColumns (QModelIndex(), 0, std::abs (diff)-1);
mMin = CellCoordinates (size.first.getX(), mMin.getY());
if (diff<0) endInsertColumns();
{
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();
}
} }
if (int diff = size.first.getY() - mMin.getY())
{ {
int diff = size.first.second - mMin.second; beginInsertRows (QModelIndex(), 0, std::abs (diff)-1);
mMin = CellCoordinates (mMin.getX(), size.first.getY());
if (diff<0) endInsertRows();
{
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();
}
} }
if (int diff = size.second.getX() - mMax.getX())
{ {
int diff = size.second.first - mMax.first; int columns = columnCount();
if (diff>0) if (diff>0)
{
int columns = columnCount();
beginInsertColumns (QModelIndex(), columns, columns+diff-1); beginInsertColumns (QModelIndex(), columns, columns+diff-1);
mMax.first = size.second.first; else
endInsertColumns();
}
else if (diff<0)
{
int columns = columnCount();
beginRemoveColumns (QModelIndex(), columns+diff, columns-1); 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) if (diff>0)
{
int rows = rowCount();
beginInsertRows (QModelIndex(), rows, rows+diff-1); beginInsertRows (QModelIndex(), rows, rows+diff-1);
mMax.second = size.second.second; else
endInsertRows();
}
else if (diff<0)
{
int rows = rowCount();
beginRemoveRows (QModelIndex(), rows+diff, rows-1); 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() std::pair<CSMWorld::CellCoordinates, CSMWorld::CellCoordinates> CSMWorld::RegionMap::getSize() const
const
{ {
const IdCollection<Cell>& cells = mData.getCells(); const IdCollection<Cell>& cells = mData.getCells();
int size = cells.getSize(); int size = cells.getSize();
CellIndex min (0, 0); CellCoordinates min (0, 0);
CellIndex max (0, 0); CellCoordinates max (0, 0);
for (int i=0; i<size; ++i) for (int i=0; i<size; ++i)
{ {
@ -269,24 +248,24 @@ std::pair<CSMWorld::RegionMap::CellIndex, CSMWorld::RegionMap::CellIndex> CSMWor
if (cell2.isExterior()) if (cell2.isExterior())
{ {
CellIndex index (cell2.mData.mX, cell2.mData.mY); CellCoordinates index = getIndex (cell2);
if (min==max) if (min==max)
{ {
min = index; min = index;
max = std::make_pair (min.first+1, min.second+1); max = min.move (1, 1);
} }
else else
{ {
if (index.first<min.first) if (index.getX()<min.getX())
min.first = index.first; min = CellCoordinates (index.getX(), min.getY());
else if (index.first>=max.first) else if (index.getX()>=max.getX())
max.first = index.first + 1; max = CellCoordinates (index.getX()+1, max.getY());
if (index.second<min.second) if (index.getY()<min.getY())
min.second = index.second; min = CellCoordinates (min.getX(), index.getY());
else if (index.second>=max.second) else if (index.getY()>=max.getY())
max.second = index.second + 1; max = CellCoordinates (max.getX(), index.getY() + 1);
} }
} }
} }
@ -323,7 +302,7 @@ int CSMWorld::RegionMap::rowCount (const QModelIndex& parent) const
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
return mMax.second-mMin.second; return mMax.getY()-mMin.getY();
} }
int CSMWorld::RegionMap::columnCount (const QModelIndex& parent) const int CSMWorld::RegionMap::columnCount (const QModelIndex& parent) const
@ -331,7 +310,7 @@ int CSMWorld::RegionMap::columnCount (const QModelIndex& parent) const
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
return mMax.first-mMin.first; return mMax.getX()-mMin.getX();
} }
QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const 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. /// \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)); mMap.find (getIndex (index));
if (cell!=mMap.end()) if (cell!=mMap.end())
@ -370,13 +349,13 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const
if (role==Qt::ToolTipRole) if (role==Qt::ToolTipRole)
{ {
CellIndex cellIndex = getIndex (index); CellCoordinates cellIndex = getIndex (index);
std::ostringstream stream; 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); mMap.find (cellIndex);
if (cell!=mMap.end()) 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()); 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(); return QVariant();
} }
Qt::ItemFlags CSMWorld::RegionMap::flags (const QModelIndex& index) const Qt::ItemFlags CSMWorld::RegionMap::flags (const QModelIndex& index) const
{ {
if (mMap.find (getIndex (index))!=mMap.end()) return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return 0;
} }
void CSMWorld::RegionMap::regionsAboutToBeRemoved (const QModelIndex& parent, int start, int end) 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(); const Cell& cell2 = cell.get();
if (cell2.isExterior()) if (cell2.isExterior())
{ removeCell (getIndex (cell2));
CellIndex index (cell2.mData.mX, cell2.mData.mY);
removeCell (index);
}
} }
} }

@ -9,6 +9,7 @@
#include "record.hpp" #include "record.hpp"
#include "cell.hpp" #include "cell.hpp"
#include "cellcoordinates.hpp"
namespace CSMWorld namespace CSMWorld
{ {
@ -23,7 +24,11 @@ namespace CSMWorld
public: public:
typedef std::pair<int, int> CellIndex; enum Role
{
Role_Region = Qt::UserRole,
Role_CellId = Qt::UserRole+1
};
private: private:
@ -39,27 +44,29 @@ namespace CSMWorld
}; };
Data& mData; Data& mData;
std::map<CellIndex, CellDescription> mMap; std::map<CellCoordinates, CellDescription> mMap;
CellIndex mMin; ///< inclusive CellCoordinates mMin; ///< inclusive
CellIndex mMax; ///< exclusive CellCoordinates mMax; ///< exclusive
std::map<std::string, unsigned int> mColours; ///< region ID, colour (RGBA) 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) ///< 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 buildRegions();
void buildMap(); 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 ///< May be called on a cell that is already in the map (in which case an update is
// performed) // performed)
void addCells (int start, int end); 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) ///< 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); void addRegion (const std::string& region, unsigned int colour);
@ -78,7 +85,7 @@ namespace CSMWorld
void updateSize(); void updateSize();
std::pair<CellIndex, CellIndex> getSize() const; std::pair<CellCoordinates, CellCoordinates> getSize() const;
public: public:
@ -89,6 +96,8 @@ namespace CSMWorld
virtual int columnCount (const QModelIndex& parent = QModelIndex()) const; virtual int columnCount (const QModelIndex& parent = QModelIndex()) const;
virtual QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) 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; 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); 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); setLayout (layout);
connect (recordFilterBox, connect (mRecordFilterBox,
SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)), SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)),
this, SIGNAL (recordFilterChanged (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)), 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); setAcceptDrops(true);
} }
void CSVFilter::FilterBox::setRecordFilter (const std::string& filter)
{
mRecordFilterBox->setFilter (filter);
}
void CSVFilter::FilterBox::dropEvent (QDropEvent* event) void CSVFilter::FilterBox::dropEvent (QDropEvent* event)
{ {
std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData(); std::vector<CSMWorld::UniversalId> data = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData())->getData();

@ -16,10 +16,14 @@ namespace CSMWorld
namespace CSVFilter namespace CSVFilter
{ {
class RecordFilterBox;
class FilterBox : public QWidget class FilterBox : public QWidget
{ {
Q_OBJECT Q_OBJECT
RecordFilterBox *mRecordFilterBox;
void dragEnterEvent (QDragEnterEvent* event); void dragEnterEvent (QDragEnterEvent* event);
void dropEvent (QDropEvent* event); void dropEvent (QDropEvent* event);
@ -30,11 +34,13 @@ namespace CSVFilter
FilterBox (CSMWorld::Data& data, QWidget *parent = 0); FilterBox (CSMWorld::Data& data, QWidget *parent = 0);
void setRecordFilter (const std::string& filter);
signals: signals:
void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter); void recordFilterChanged (boost::shared_ptr<CSMFilter::Node> filter);
void recordDropped (std::vector<CSMWorld::UniversalId>& types, Qt::DropAction action); 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); Qt::DropAction action);
void useFilterRequest(const std::string& idOfFilter); 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)); 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); setLayout (layout);
connect ( 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>))); this, SIGNAL (filterChanged (boost::shared_ptr<CSMFilter::Node>)));
connect(this, SIGNAL(createFilterRequest(std::vector<std::pair<std::string, std::vector<std::string> > >&, Qt::DropAction)), 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 namespace CSVFilter
{ {
class EditWidget;
class RecordFilterBox : public QWidget class RecordFilterBox : public QWidget
{ {
Q_OBJECT Q_OBJECT
EditWidget *mEdit;
public: public:
RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0); RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0);
void setFilter (const std::string& filter);
signals: signals:
void filterChanged (boost::shared_ptr<CSMFilter::Node> filter); 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 "regionmapsubview.hpp"
#include <QTableView> #include "regionmap.hpp"
#include <QHeaderView>
CSVWorld::RegionMapSubView::RegionMapSubView (CSMWorld::UniversalId universalId, CSVWorld::RegionMapSubView::RegionMapSubView (CSMWorld::UniversalId universalId,
CSMDoc::Document& document) CSMDoc::Document& document)
: CSVDoc::SubView (universalId) : CSVDoc::SubView (universalId)
{ {
mTable = new QTableView (this); mRegionMap = new RegionMap (universalId, document, this);
mTable->verticalHeader()->hide(); setWidget (mRegionMap);
mTable->horizontalHeader()->hide();
mTable->setSelectionMode (QAbstractItemView::ExtendedSelection); connect (mRegionMap, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)),
this, SLOT (editRequest (const CSMWorld::UniversalId&, const std::string&)));
mTable->setModel (document.getData().getTableModel (universalId));
mTable->resizeColumnsToContents();
mTable->resizeRowsToContents();
setWidget (mTable);
} }
void CSVWorld::RegionMapSubView::setEditLock (bool locked) 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" #include "../doc/subview.hpp"
class QTableView; class QAction;
namespace CSMDoc namespace CSMDoc
{ {
@ -12,15 +12,23 @@ namespace CSMDoc
namespace CSVWorld namespace CSVWorld
{ {
class RegionMap;
class RegionMapSubView : public CSVDoc::SubView class RegionMapSubView : public CSVDoc::SubView
{ {
QTableView *mTable; Q_OBJECT
RegionMap *mRegionMap;
public: public:
RegionMapSubView (CSMWorld::UniversalId universalId, CSMDoc::Document& document); RegionMapSubView (CSMWorld::UniversalId universalId, CSMDoc::Document& document);
virtual void setEditLock (bool locked); 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() void CSVWorld::Table::moveUpRecord()
{ {
if (mEditLock)
return;
QModelIndexList selectedRows = selectionModel()->selectedRows(); QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.size()==1) if (selectedRows.size()==1)
@ -387,6 +390,9 @@ void CSVWorld::Table::moveUpRecord()
void CSVWorld::Table::moveDownRecord() void CSVWorld::Table::moveDownRecord()
{ {
if (mEditLock)
return;
QModelIndexList selectedRows = selectionModel()->selectedRows(); QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.size()==1) if (selectedRows.size()==1)

@ -26,9 +26,9 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
layout->insertWidget (0, mTable = layout->insertWidget (0, mTable =
new Table (id, mBottom->canCreateAndDelete(), sorting, document), 2); 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; QWidget *widget = new QWidget;
@ -48,7 +48,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
mTable->selectionSizeUpdate(); mTable->selectionSizeUpdate();
mTable->viewport()->installEventFilter(this); mTable->viewport()->installEventFilter(this);
mBottom->installEventFilter(this); mBottom->installEventFilter(this);
filterBox->installEventFilter(this); mFilterBox->installEventFilter(this);
if (mBottom->canCreateAndDelete()) if (mBottom->canCreateAndDelete())
{ {
@ -63,17 +63,17 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
connect (mBottom, SIGNAL (requestFocus (const std::string&)), connect (mBottom, SIGNAL (requestFocus (const std::string&)),
mTable, SLOT (requestFocus (const std::string&))); mTable, SLOT (requestFocus (const std::string&)));
connect (filterBox, connect (mFilterBox,
SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)), SIGNAL (recordFilterChanged (boost::shared_ptr<CSMFilter::Node>)),
mTable, SLOT (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))); 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)), 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) void CSVWorld::TableSubView::setEditLock (bool locked)
@ -97,6 +97,15 @@ void CSVWorld::TableSubView::setStatusBar (bool show)
mBottom->setStatusBar (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) void CSVWorld::TableSubView::cloneRequest(const CSMWorld::UniversalId& toClone)
{ {
emit cloneRequest(toClone.getId(), toClone.getType()); emit cloneRequest(toClone.getId(), toClone.getType());

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

Loading…
Cancel
Save