mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-07-13 09:21:42 +00:00
Merge branch 'regionmap'
This commit is contained in:
commit
71068ae3ad
15 changed files with 625 additions and 139 deletions
|
@ -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);
|
||||||
|
|
346
apps/opencs/view/world/regionmap.cpp
Normal file
346
apps/opencs/view/world/regionmap.cpp
Normal file
|
@ -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());
|
||||||
|
}
|
84
apps/opencs/view/world/regionmap.hpp
Normal file
84
apps/opencs/view/world/regionmap.hpp
Normal file
|
@ -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…
Reference in a new issue