#include <QAbstractProxyModel>
{
Q_OBJECT
public:
~MergeProxyModel();
void setColumnCount(int count) { column_count=count; };
int getListPos(int n) const;
protected:
int column_count;
int listsCount() const;
private:
private slots:
void rowsAboutToBeInsertedSlot
(const QModelIndex &parent,
int first,
int last
);
void rowsInsertedSlot
(const QModelIndex &parent,
int first,
int last
);
void rowsAboutToBeRemovedSlot
(const QModelIndex &parent,
int first,
int last
);
void rowsRemovedSlot
(const QModelIndex &parent,
int first,
int last
);
void modelAboutToBeResetSlot();
void modelResetSlot();
};
column_count(1),
first_model(_first_model),
second_model(_second_model),
third_model(_third_model)
{
if (first_model) connectModels(first_model);
if (second_model) connectModels(second_model);
if (third_model) connectModels(third_model);
}
MergeProxyModel::~MergeProxyModel()
{
}
{
Q_ASSERT(model);
connect(model, SIGNAL(layoutAboutToBeChanged()), this, SIGNAL(layoutAboutToBeChanged()), Qt::DirectConnection);
connect(model, SIGNAL(layoutChanged()), this, SIGNAL(layoutChanged()), Qt::DirectConnection);
connect(model,
SIGNAL(rowsAboutToBeInserted
(QModelIndex,
int,
int)),
this,
SLOT(rowsAboutToBeInsertedSlot
(QModelIndex,
int,
int)), Qt
::DirectConnection);
connect(model,
SIGNAL(rowsInserted
(QModelIndex,
int,
int)),
this,
SLOT(rowsInsertedSlot
(QModelIndex,
int,
int)), Qt
::DirectConnection);
connect(model,
SIGNAL(rowsAboutToBeRemoved
(QModelIndex,
int,
int)),
this,
SLOT(rowsAboutToBeRemovedSlot
(QModelIndex,
int,
int)), Qt
::DirectConnection);
connect(model,
SIGNAL(rowsRemoved
(QModelIndex,
int,
int)),
this,
SLOT(rowsRemovedSlot
(QModelIndex,
int,
int)), Qt
::DirectConnection);
connect(model, SIGNAL(modelAboutToBeReset()), this, SLOT(modelAboutToBeResetSlot()), Qt::DirectConnection);
connect(model, SIGNAL(modelReset()), this, SLOT(modelResetSlot()), Qt::DirectConnection);
}
int MergeProxyModel::listsCount() const
{
int totalCount = 0;
if (first_model) totalCount += first_model->rowCount();
if (second_model) totalCount += second_model->rowCount();
if (third_model) totalCount += third_model->rowCount();
return totalCount;
}
bool MergeProxyModel
::indexCheck(const QModelIndex &index
) const {
return (index.isValid() && index.row() >= 0 && index.row() < rowCount() && index.column() >= 0 && index.column() < columnCount());
}
Qt
::ItemFlags MergeProxyModel
::flags(const QModelIndex &index
) const{
Qt::ItemFlags theFlags = Qt::NoItemFlags;
return theFlags;
}
{
if (!indexCheck
(index
)) return QVariant();
switch (getListNo(index))
{
case 0: return first_model->data(mapToSource(index), role);
case 1: return second_model->data(mapToSource(index), role);
case 2: return third_model->data(mapToSource(index), role);
}
}
int MergeProxyModel
::rowCount(const QModelIndex &index
) const {
return index.isValid() ? 0 : listsCount();
}
int MergeProxyModel
::columnCount(const QModelIndex &index
) const {
return index.isValid() ? 0 : column_count;
}
{
int offset = 0;
if (smodel != first_model) {
if (first_model) offset += first_model->rowCount();
if (smodel != second_model) {
if (second_model) offset += second_model->rowCount();
}
}
return offset;
}
{
else if (sourceIndex.
parent().
isValid()) return QModelIndex();
int offset = getOffset(sourceIndex.model());
return createIndex(sourceIndex.row() + offset, sourceIndex.column());
}
{
int pos = getListPos(proxyIndex);
return smodel->index(pos, proxyIndex.column());
}
{
return createIndex(row, column, getListPos(row));
}
{
}
int MergeProxyModel
::getListNo(const QModelIndex &index
) const {
if (index.isValid())
{
int n = index.row();
int offset = 0;
if (first_model) {
if (n < first_model->rowCount()) return 0;
offset += first_model->rowCount();
}
if (second_model) {
if (n-offset < second_model->rowCount()) return 1;
offset += second_model->rowCount();
}
if (third_model) {
if (n-offset < third_model->rowCount()) return 2;
}
}
return -1;
}
int MergeProxyModel::getListPos(int n) const
{
if (first_model) {
if (n < first_model->rowCount()) return n;
n -= first_model->rowCount();
}
if (second_model) {
if (n < second_model->rowCount()) return n;
n -= second_model->rowCount();
}
if (third_model) {
if (n < third_model->rowCount()) return n;
}
return -1;
}
int MergeProxyModel
::getListPos(const QModelIndex &index
) const {
if (index.isValid())
{
int n = index.row();
if (first_model) {
if (n < first_model->rowCount()) return n;
n -= first_model->rowCount();
}
if (second_model) {
if (n < second_model->rowCount()) return n;
n -= second_model->rowCount();
}
if (third_model) {
if (n < third_model->rowCount()) return n;
}
}
return -1;
}
{
switch (getListNo(index))
{
case 0: return first_model;
case 1: return second_model;
case 2: return third_model;
default: return 0;
}
}
{
const QModelIndex &proxyTopLeft
= mapFromSource
(topLeft
);
const QModelIndex &proxyBottomRight
= mapFromSource
(bottomRight
);
emit dataChanged(proxyTopLeft, proxyBottomRight);
}
void MergeProxyModel
::rowsAboutToBeInsertedSlot(const QModelIndex &parent,
int first,
int last
) {
beginInsertRows(parent, first, last);
}
void MergeProxyModel
::rowsInsertedSlot(const QModelIndex &parent,
int first,
int last
) {
endInsertRows();
}
void MergeProxyModel
::rowsAboutToBeRemovedSlot(const QModelIndex &parent,
int first,
int last
) {
const int offset = getOffset(smodel);
beginRemoveRows(parent, first + offset, last + offset);
}
void MergeProxyModel
::rowsRemovedSlot(const QModelIndex &parent,
int first,
int last
) {
endRemoveRows();
}
void MergeProxyModel::modelAboutToBeResetSlot()
{
beginResetModel();
}
void MergeProxyModel::modelResetSlot()
{
endResetModel();
}
#include <QAbstractProxyModel>
class MergeProxyModel : public QAbstractProxyModel
{
Q_OBJECT
public:
MergeProxyModel(QAbstractTableModel* first_model=0, QAbstractTableModel* second_model=0, QAbstractTableModel* third_model=0, QObject* parent=0);
~MergeProxyModel();
void setColumnCount(int count) { column_count=count; };
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
int rowCount(const QModelIndex &index=QModelIndex()) const;
int columnCount(const QModelIndex &index=QModelIndex()) const;
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &proxyChild) const;
bool indexCheck(const QModelIndex &index) const;
int getListNo(const QModelIndex &index) const;
int getListPos(int n) const;
int getListPos(const QModelIndex &index) const;
QAbstractTableModel* sourceModel(const QModelIndex &index) const;
protected:
int column_count;
int listsCount() const;
int getOffset(const QAbstractItemModel* smodel) const;
QAbstractTableModel* first_model;
QAbstractTableModel* second_model;
QAbstractTableModel* third_model;
private:
void connectModels(QAbstractTableModel* model);
private slots:
void dataChangedSlot(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void rowsAboutToBeInsertedSlot(const QModelIndex &parent, int first, int last);
void rowsInsertedSlot(const QModelIndex &parent, int first, int last);
void rowsAboutToBeRemovedSlot(const QModelIndex &parent, int first, int last);
void rowsRemovedSlot(const QModelIndex &parent, int first, int last);
void modelAboutToBeResetSlot();
void modelResetSlot();
};
MergeProxyModel::MergeProxyModel(QAbstractTableModel* _first_model,
QAbstractTableModel* _second_model,
QAbstractTableModel* _third_model,
QObject *_parent)
: QAbstractProxyModel(_parent),
column_count(1),
first_model(_first_model),
second_model(_second_model),
third_model(_third_model)
{
if (first_model) connectModels(first_model);
if (second_model) connectModels(second_model);
if (third_model) connectModels(third_model);
}
MergeProxyModel::~MergeProxyModel()
{
}
void MergeProxyModel::connectModels(QAbstractTableModel* model)
{
Q_ASSERT(model);
connect(model, SIGNAL(layoutAboutToBeChanged()), this, SIGNAL(layoutAboutToBeChanged()), Qt::DirectConnection);
connect(model, SIGNAL(layoutChanged()), this, SIGNAL(layoutChanged()), Qt::DirectConnection);
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChangedSlot(QModelIndex,QModelIndex)), Qt::DirectConnection);
connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(rowsAboutToBeInsertedSlot(QModelIndex,int,int)), Qt::DirectConnection);
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInsertedSlot(QModelIndex,int,int)), Qt::DirectConnection);
connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(rowsAboutToBeRemovedSlot(QModelIndex,int,int)), Qt::DirectConnection);
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(rowsRemovedSlot(QModelIndex,int,int)), Qt::DirectConnection);
connect(model, SIGNAL(modelAboutToBeReset()), this, SLOT(modelAboutToBeResetSlot()), Qt::DirectConnection);
connect(model, SIGNAL(modelReset()), this, SLOT(modelResetSlot()), Qt::DirectConnection);
}
int MergeProxyModel::listsCount() const
{
int totalCount = 0;
if (first_model) totalCount += first_model->rowCount();
if (second_model) totalCount += second_model->rowCount();
if (third_model) totalCount += third_model->rowCount();
return totalCount;
}
bool MergeProxyModel::indexCheck(const QModelIndex &index) const
{
return (index.isValid() && index.row() >= 0 && index.row() < rowCount() && index.column() >= 0 && index.column() < columnCount());
}
Qt::ItemFlags MergeProxyModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags theFlags = Qt::NoItemFlags;
if (index.isValid()) return QAbstractProxyModel::flags(index);
return theFlags;
}
QVariant MergeProxyModel::data(const QModelIndex &index, int role) const
{
if (!indexCheck(index)) return QVariant();
switch (getListNo(index))
{
case 0: return first_model->data(mapToSource(index), role);
case 1: return second_model->data(mapToSource(index), role);
case 2: return third_model->data(mapToSource(index), role);
default: return QVariant();
}
return QVariant();
}
int MergeProxyModel::rowCount(const QModelIndex &index) const
{
return index.isValid() ? 0 : listsCount();
}
int MergeProxyModel::columnCount(const QModelIndex &index) const
{
return index.isValid() ? 0 : column_count;
}
int MergeProxyModel::getOffset(const QAbstractItemModel* smodel) const
{
int offset = 0;
if (smodel != first_model) {
if (first_model) offset += first_model->rowCount();
if (smodel != second_model) {
if (second_model) offset += second_model->rowCount();
}
}
return offset;
}
QModelIndex MergeProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
if (!sourceIndex.isValid()) return QModelIndex();
else if (sourceIndex.parent().isValid()) return QModelIndex();
int offset = getOffset(sourceIndex.model());
return createIndex(sourceIndex.row() + offset, sourceIndex.column());
}
QModelIndex MergeProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
if (!proxyIndex.isValid()) return QModelIndex();
int pos = getListPos(proxyIndex);
QAbstractTableModel* smodel = sourceModel(proxyIndex);
if (!smodel) return QModelIndex();
return smodel->index(pos, proxyIndex.column());
}
QModelIndex MergeProxyModel::index(int row, int column, const QModelIndex &parent) const
{
if (row >= rowCount()) return QModelIndex();
return createIndex(row, column, getListPos(row));
}
QModelIndex MergeProxyModel::parent(const QModelIndex &proxyChild) const
{
return QModelIndex();
}
int MergeProxyModel::getListNo(const QModelIndex &index) const
{
if (index.isValid())
{
int n = index.row();
int offset = 0;
if (first_model) {
if (n < first_model->rowCount()) return 0;
offset += first_model->rowCount();
}
if (second_model) {
if (n-offset < second_model->rowCount()) return 1;
offset += second_model->rowCount();
}
if (third_model) {
if (n-offset < third_model->rowCount()) return 2;
}
}
return -1;
}
int MergeProxyModel::getListPos(int n) const
{
if (first_model) {
if (n < first_model->rowCount()) return n;
n -= first_model->rowCount();
}
if (second_model) {
if (n < second_model->rowCount()) return n;
n -= second_model->rowCount();
}
if (third_model) {
if (n < third_model->rowCount()) return n;
}
return -1;
}
int MergeProxyModel::getListPos(const QModelIndex &index) const
{
if (index.isValid())
{
int n = index.row();
if (first_model) {
if (n < first_model->rowCount()) return n;
n -= first_model->rowCount();
}
if (second_model) {
if (n < second_model->rowCount()) return n;
n -= second_model->rowCount();
}
if (third_model) {
if (n < third_model->rowCount()) return n;
}
}
return -1;
}
QAbstractTableModel* MergeProxyModel::sourceModel(const QModelIndex &index) const
{
switch (getListNo(index))
{
case 0: return first_model;
case 1: return second_model;
case 2: return third_model;
default: return 0;
}
}
void MergeProxyModel::dataChangedSlot(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
const QModelIndex &proxyTopLeft = mapFromSource(topLeft);
const QModelIndex &proxyBottomRight = mapFromSource(bottomRight);
emit dataChanged(proxyTopLeft, proxyBottomRight);
}
void MergeProxyModel::rowsAboutToBeInsertedSlot(const QModelIndex &parent, int first, int last)
{
beginInsertRows(parent, first, last);
}
void MergeProxyModel::rowsInsertedSlot(const QModelIndex &parent, int first, int last)
{
endInsertRows();
}
void MergeProxyModel::rowsAboutToBeRemovedSlot(const QModelIndex &parent, int first, int last)
{
QAbstractTableModel *smodel = qobject_cast<QAbstractTableModel *>(sender());
const int offset = getOffset(smodel);
beginRemoveRows(parent, first + offset, last + offset);
}
void MergeProxyModel::rowsRemovedSlot(const QModelIndex &parent, int first, int last)
{
endRemoveRows();
}
void MergeProxyModel::modelAboutToBeResetSlot()
{
beginResetModel();
}
void MergeProxyModel::modelResetSlot()
{
endResetModel();
}
To copy to clipboard, switch view to plain text mode
Bookmarks