forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'smbas/fix-bug-2728'
This commit is contained in:
commit
420503d5fc
6 changed files with 116 additions and 45 deletions
|
@ -7,23 +7,23 @@
|
||||||
|
|
||||||
void CSMWorld::IdTableProxyModel::updateColumnMap()
|
void CSMWorld::IdTableProxyModel::updateColumnMap()
|
||||||
{
|
{
|
||||||
mColumnMap.clear();
|
Q_ASSERT(mSourceModel != NULL);
|
||||||
|
|
||||||
|
mColumnMap.clear();
|
||||||
if (mFilter)
|
if (mFilter)
|
||||||
{
|
{
|
||||||
std::vector<int> columns = mFilter->getReferencedColumns();
|
std::vector<int> columns = mFilter->getReferencedColumns();
|
||||||
|
|
||||||
const IdTableBase& table = dynamic_cast<const IdTableBase&> (*sourceModel());
|
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator iter (columns.begin()); iter!=columns.end(); ++iter)
|
for (std::vector<int>::const_iterator iter (columns.begin()); iter!=columns.end(); ++iter)
|
||||||
mColumnMap.insert (std::make_pair (*iter,
|
mColumnMap.insert (std::make_pair (*iter,
|
||||||
table.searchColumnIndex (static_cast<CSMWorld::Columns::ColumnId> (*iter))));
|
mSourceModel->searchColumnIndex (static_cast<CSMWorld::Columns::ColumnId> (*iter))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent)
|
bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(mSourceModel != NULL);
|
||||||
|
|
||||||
// It is not possible to use filterAcceptsColumn() and check for
|
// It is not possible to use filterAcceptsColumn() and check for
|
||||||
// sourceModel()->headerData (sourceColumn, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags)
|
// sourceModel()->headerData (sourceColumn, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags)
|
||||||
// because the sourceColumn parameter excludes the hidden columns, i.e. wrong columns can
|
// because the sourceColumn parameter excludes the hidden columns, i.e. wrong columns can
|
||||||
|
@ -35,34 +35,37 @@ bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelI
|
||||||
if (!mFilter)
|
if (!mFilter)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return mFilter->test (
|
return mFilter->test (*mSourceModel, sourceRow, mColumnMap);
|
||||||
dynamic_cast<IdTableBase&> (*sourceModel()), sourceRow, mColumnMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
|
CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
|
||||||
: QSortFilterProxyModel (parent)
|
: QSortFilterProxyModel (parent),
|
||||||
|
mSourceModel(NULL)
|
||||||
{
|
{
|
||||||
setSortCaseSensitivity (Qt::CaseInsensitive);
|
setSortCaseSensitivity (Qt::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const
|
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const
|
||||||
{
|
{
|
||||||
return mapFromSource (dynamic_cast<IdTableBase&> (*sourceModel()).getModelIndex (id, column));
|
Q_ASSERT(mSourceModel != NULL);
|
||||||
|
|
||||||
|
return mapFromSource(mSourceModel->getModelIndex (id, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::IdTableProxyModel::setSourceModel(QAbstractItemModel *model)
|
void CSMWorld::IdTableProxyModel::setSourceModel(QAbstractItemModel *model)
|
||||||
{
|
{
|
||||||
QSortFilterProxyModel::setSourceModel(model);
|
QSortFilterProxyModel::setSourceModel(model);
|
||||||
|
|
||||||
connect(sourceModel(),
|
mSourceModel = dynamic_cast<IdTableBase *>(sourceModel());
|
||||||
SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
|
connect(mSourceModel,
|
||||||
this,
|
|
||||||
SLOT(sourceRowsChanged(const QModelIndex &, int, int)));
|
|
||||||
connect(sourceModel(),
|
|
||||||
SIGNAL(rowsInserted(const QModelIndex &, int, int)),
|
SIGNAL(rowsInserted(const QModelIndex &, int, int)),
|
||||||
this,
|
this,
|
||||||
SLOT(sourceRowsChanged(const QModelIndex &, int, int)));
|
SLOT(sourceRowsInserted(const QModelIndex &, int, int)));
|
||||||
connect(sourceModel(),
|
connect(mSourceModel,
|
||||||
|
SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
|
||||||
|
this,
|
||||||
|
SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
|
||||||
|
connect(mSourceModel,
|
||||||
SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
|
SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
|
||||||
this,
|
this,
|
||||||
SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex &)));
|
SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex &)));
|
||||||
|
@ -95,13 +98,30 @@ bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex &left, const QModel
|
||||||
return QSortFilterProxyModel::lessThan(left, right);
|
return QSortFilterProxyModel::lessThan(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CSMWorld::IdTableProxyModel::getRecordId(int sourceRow) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(mSourceModel != NULL);
|
||||||
|
|
||||||
|
int idColumn = mSourceModel->findColumnIndex(Columns::ColumnId_Id);
|
||||||
|
return mSourceModel->data(mSourceModel->index(sourceRow, idColumn)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
void CSMWorld::IdTableProxyModel::refreshFilter()
|
void CSMWorld::IdTableProxyModel::refreshFilter()
|
||||||
{
|
{
|
||||||
updateColumnMap();
|
updateColumnMap();
|
||||||
invalidateFilter();
|
invalidateFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::IdTableProxyModel::sourceRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/)
|
void CSMWorld::IdTableProxyModel::sourceRowsInserted(const QModelIndex &parent, int /*start*/, int end)
|
||||||
|
{
|
||||||
|
refreshFilter();
|
||||||
|
if (!parent.isValid())
|
||||||
|
{
|
||||||
|
emit rowAdded(getRecordId(end).toUtf8().constData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::IdTableProxyModel::sourceRowsRemoved(const QModelIndex &/*parent*/, int /*start*/, int /*end*/)
|
||||||
{
|
{
|
||||||
refreshFilter();
|
refreshFilter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,10 @@ namespace CSMWorld
|
||||||
typedef std::map<Columns::ColumnId, std::vector<std::string> > EnumColumnCache;
|
typedef std::map<Columns::ColumnId, std::vector<std::string> > EnumColumnCache;
|
||||||
mutable EnumColumnCache mEnumColumnCache;
|
mutable EnumColumnCache mEnumColumnCache;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
IdTableBase *mSourceModel;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void updateColumnMap();
|
void updateColumnMap();
|
||||||
|
@ -45,15 +49,23 @@ namespace CSMWorld
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||||
|
|
||||||
virtual bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const;
|
virtual bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const;
|
||||||
|
|
||||||
private slots:
|
QString getRecordId(int sourceRow) const;
|
||||||
|
|
||||||
void sourceRowsChanged(const QModelIndex &parent, int start, int end);
|
protected slots:
|
||||||
|
|
||||||
void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
virtual void sourceRowsInserted(const QModelIndex &parent, int start, int end);
|
||||||
|
|
||||||
|
virtual void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
|
||||||
|
|
||||||
|
virtual void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void rowAdded(const std::string &id);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,17 @@ namespace
|
||||||
{
|
{
|
||||||
QString toLower(const QString &str)
|
QString toLower(const QString &str)
|
||||||
{
|
{
|
||||||
return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toStdString()).c_str());
|
return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toUtf8().constData()).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent)
|
CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent)
|
||||||
: IdTableProxyModel(parent),
|
: IdTableProxyModel(parent),
|
||||||
mType(type),
|
mType(type),
|
||||||
mSourceModel(NULL),
|
|
||||||
mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic :
|
mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic :
|
||||||
Columns::ColumnId_Journal)
|
Columns::ColumnId_Journal),
|
||||||
|
mInfoColumnIndex(-1),
|
||||||
|
mLastAddedSourceRow(-1)
|
||||||
{
|
{
|
||||||
Q_ASSERT(type == UniversalId::Type_TopicInfos || type == UniversalId::Type_JournalInfos);
|
Q_ASSERT(type == UniversalId::Type_TopicInfos || type == UniversalId::Type_JournalInfos);
|
||||||
}
|
}
|
||||||
|
@ -26,23 +27,18 @@ CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type t
|
||||||
void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||||
{
|
{
|
||||||
IdTableProxyModel::setSourceModel(sourceModel);
|
IdTableProxyModel::setSourceModel(sourceModel);
|
||||||
mSourceModel = dynamic_cast<IdTableBase *>(sourceModel);
|
|
||||||
if (mSourceModel != NULL)
|
if (mSourceModel != NULL)
|
||||||
{
|
{
|
||||||
connect(mSourceModel,
|
mInfoColumnIndex = mSourceModel->findColumnIndex(mInfoColumnId);
|
||||||
SIGNAL(rowsInserted(const QModelIndex &, int, int)),
|
|
||||||
this,
|
|
||||||
SLOT(modelRowsChanged(const QModelIndex &, int, int)));
|
|
||||||
connect(mSourceModel,
|
|
||||||
SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
|
|
||||||
this,
|
|
||||||
SLOT(modelRowsChanged(const QModelIndex &, int, int)));
|
|
||||||
mFirstRowCache.clear();
|
mFirstRowCache.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(mSourceModel != NULL);
|
||||||
|
|
||||||
QModelIndex first = mSourceModel->index(getFirstInfoRow(left.row()), left.column());
|
QModelIndex first = mSourceModel->index(getFirstInfoRow(left.row()), left.column());
|
||||||
QModelIndex second = mSourceModel->index(getFirstInfoRow(right.row()), right.column());
|
QModelIndex second = mSourceModel->index(getFirstInfoRow(right.row()), right.column());
|
||||||
|
|
||||||
|
@ -56,8 +52,10 @@ bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QMod
|
||||||
|
|
||||||
int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const
|
int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(mSourceModel != NULL);
|
||||||
|
|
||||||
int row = currentRow;
|
int row = currentRow;
|
||||||
int column = mSourceModel->findColumnIndex(mInfoColumnId);
|
int column = mInfoColumnIndex;
|
||||||
QString info = toLower(mSourceModel->data(mSourceModel->index(row, column)).toString());
|
QString info = toLower(mSourceModel->data(mSourceModel->index(row, column)).toString());
|
||||||
|
|
||||||
if (mFirstRowCache.contains(info))
|
if (mFirstRowCache.contains(info))
|
||||||
|
@ -73,7 +71,41 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::InfoTableProxyModel::modelRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/)
|
void CSMWorld::InfoTableProxyModel::sourceRowsRemoved(const QModelIndex &/*parent*/, int /*start*/, int /*end*/)
|
||||||
{
|
{
|
||||||
|
refreshFilter();
|
||||||
mFirstRowCache.clear();
|
mFirstRowCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::InfoTableProxyModel::sourceRowsInserted(const QModelIndex &parent, int /*start*/, int end)
|
||||||
|
{
|
||||||
|
refreshFilter();
|
||||||
|
|
||||||
|
if (!parent.isValid())
|
||||||
|
{
|
||||||
|
mFirstRowCache.clear();
|
||||||
|
// We can't re-sort the model here, because the topic of the added row isn't set yet.
|
||||||
|
// Store the row index for using in the first dataChanged() after this row insertion.
|
||||||
|
mLastAddedSourceRow = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::InfoTableProxyModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
|
||||||
|
{
|
||||||
|
refreshFilter();
|
||||||
|
|
||||||
|
if (mLastAddedSourceRow != -1 &&
|
||||||
|
topLeft.row() <= mLastAddedSourceRow && bottomRight.row() >= mLastAddedSourceRow)
|
||||||
|
{
|
||||||
|
// Now the topic of the last added row is set,
|
||||||
|
// so we can re-sort the model to ensure the corrent position of this row
|
||||||
|
int column = sortColumn();
|
||||||
|
Qt::SortOrder order = sortOrder();
|
||||||
|
sort(mInfoColumnIndex); // Restore the correct position of an added row
|
||||||
|
sort(column, order); // Restore the original sort order
|
||||||
|
emit rowAdded(getRecordId(mLastAddedSourceRow).toUtf8().constData());
|
||||||
|
|
||||||
|
// Make sure that we perform a re-sorting only in the first dataChanged() after a row insertion
|
||||||
|
mLastAddedSourceRow = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,25 +16,29 @@ namespace CSMWorld
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
UniversalId::Type mType;
|
UniversalId::Type mType;
|
||||||
IdTableBase *mSourceModel;
|
|
||||||
Columns::ColumnId mInfoColumnId;
|
Columns::ColumnId mInfoColumnId;
|
||||||
///< Contains ID for Topic or Journal ID
|
///< Contains ID for Topic or Journal ID
|
||||||
|
int mInfoColumnIndex;
|
||||||
|
int mLastAddedSourceRow;
|
||||||
|
|
||||||
mutable QHash<QString, int> mFirstRowCache;
|
mutable QHash<QString, int> mFirstRowCache;
|
||||||
|
|
||||||
int getFirstInfoRow(int currentRow) const;
|
int getFirstInfoRow(int currentRow) const;
|
||||||
///< Finds the first row with the same topic (journal entry) as in \a currentRow
|
///< Finds the first row with the same topic (journal entry) as in \a currentRow
|
||||||
|
///< \a currentRow is a row of the source model.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InfoTableProxyModel(UniversalId::Type type, QObject *parent = 0);
|
InfoTableProxyModel(UniversalId::Type type, QObject *parent = 0);
|
||||||
|
|
||||||
void setSourceModel(QAbstractItemModel *sourceModel);
|
virtual void setSourceModel(QAbstractItemModel *sourceModel);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||||
|
|
||||||
private slots:
|
protected slots:
|
||||||
void modelRowsChanged(const QModelIndex &parent, int start, int end);
|
virtual void sourceRowsInserted(const QModelIndex &parent, int start, int end);
|
||||||
|
virtual void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
|
||||||
|
virtual void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -371,8 +371,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
||||||
connect (mProxyModel, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
|
connect (mProxyModel, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
|
||||||
this, SLOT (tableSizeUpdate()));
|
this, SLOT (tableSizeUpdate()));
|
||||||
|
|
||||||
connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
//connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
this, SLOT (rowsInsertedEvent(const QModelIndex&, int, int)));
|
// this, SLOT (rowsInsertedEvent(const QModelIndex&, int, int)));
|
||||||
|
connect (mProxyModel, SIGNAL (rowAdded (const std::string &)),
|
||||||
|
this, SLOT (rowAdded (const std::string &)));
|
||||||
|
|
||||||
/// \note This signal could instead be connected to a slot that filters out changes not affecting
|
/// \note This signal could instead be connected to a slot that filters out changes not affecting
|
||||||
/// the records status column (for permanence reasons)
|
/// the records status column (for permanence reasons)
|
||||||
|
@ -714,12 +716,13 @@ std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const
|
||||||
return idToDrag;
|
return idToDrag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::rowsInsertedEvent(const QModelIndex& parent, int start, int end)
|
void CSVWorld::Table::rowAdded(const std::string &id)
|
||||||
{
|
{
|
||||||
tableSizeUpdate();
|
tableSizeUpdate();
|
||||||
if(mJumpToAddedRecord)
|
if(mJumpToAddedRecord)
|
||||||
{
|
{
|
||||||
selectRow(end);
|
int idColumn = mModel->findColumnIndex(CSMWorld::Columns::ColumnId_Id);
|
||||||
|
selectRow(mProxyModel->getModelIndex(id, idColumn).row());
|
||||||
|
|
||||||
if(mUnselectAfterJump)
|
if(mUnselectAfterJump)
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
|
|
@ -140,7 +140,7 @@ namespace CSVWorld
|
||||||
|
|
||||||
void updateUserSetting (const QString &name, const QStringList &list);
|
void updateUserSetting (const QString &name, const QStringList &list);
|
||||||
|
|
||||||
void rowsInsertedEvent(const QModelIndex& parent, int start, int end);
|
void rowAdded(const std::string &id);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue