/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
* Version : %version: 7 %
*/
#include <QList>
#include <QAbstractItemModel>
#include <hgwidgets/hgcacheproxymodel.h>
#include <hgwidgets/hgdataprovidermodel.h>
#include "hgbuffermanager.h"
#include "hglogger.h"
HgCacheProxyModel::HgCacheProxyModel(QObject *parent):
QAbstractItemModel(parent),
mBufferManager(0),
mSortFilterProxyModel(new QSortFilterProxyModel(this)),
mDataProviderModel(0),
mSupressBM(false),
mCurrentPos(0)//,
// mSortParameterChanged(true)
{
TX_ENTRY
connect(mSortFilterProxyModel, SIGNAL(columnsAboutToBeInserted(const QModelIndex&, int, int)),
this, SLOT(sourceColumnsAboutToBeInserted(const QModelIndex&, int, int)));
connect(mSortFilterProxyModel, SIGNAL(columnsAboutToBeMoved(const QModelIndex&, int, int, const QModelIndex&, int)),
this, SLOT(sourceColumnsAboutToBeMoved(const QModelIndex&, int, int, const QModelIndex&, int)));
connect(mSortFilterProxyModel, SIGNAL(columnsAboutToBeRemoved(const QModelIndex&, int, int)),
this, SLOT(sourceColumnsAboutToBeRemoved(const QModelIndex&, int, int)));
connect(mSortFilterProxyModel, SIGNAL(columnsInserted(const QModelIndex&, int, int)),
this, SLOT(sourceColumnsInserted(const QModelIndex&, int, int)));
connect(mSortFilterProxyModel, SIGNAL(columnsMoved(const QModelIndex&, int, int, const QModelIndex&, int)),
this, SLOT(sourceColumnsMoved(const QModelIndex&, int, int, const QModelIndex&, int)));
connect(mSortFilterProxyModel, SIGNAL(columnsRemoved(const QModelIndex&, int, int )),
this, SLOT(sourceColumnsRemoved(const QModelIndex&, int, int )));
connect(mSortFilterProxyModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(sourceDataChanged(const QModelIndex&, const QModelIndex&)));
connect(mSortFilterProxyModel, SIGNAL(headerDataChanged(Qt::Orientation, int, int)),
this, SLOT(sourceHeaderDataChanged(Qt::Orientation, int, int)));
connect(mSortFilterProxyModel, SIGNAL(layoutAboutToBeChanged()),
this, SLOT(sourceLayoutAboutToBeChanged()));
connect(mSortFilterProxyModel, SIGNAL(layoutChanged()),
this, SLOT(sourceLayoutChanged()));
connect(mSortFilterProxyModel, SIGNAL(modelAboutToBeReset()),
this, SLOT(sourceModelAboutToBeReset()));
connect(mSortFilterProxyModel, SIGNAL(modelReset()),
this, SLOT(sourceModelReset()));
connect(mSortFilterProxyModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex&, int, int)),
this, SLOT(sourceRowsAboutToBeInserted(const QModelIndex&, int, int)));
connect(mSortFilterProxyModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex&, int, int, const QModelIndex&, int)),
this, SLOT(sourceRowsAboutToBeMoved(const QModelIndex&, int, int, const QModelIndex&, int)));
connect(mSortFilterProxyModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)),
this, SLOT(sourceRowsAboutToBeRemoved(const QModelIndex&, int, int)));
connect(mSortFilterProxyModel, SIGNAL(rowsInserted(const QModelIndex &, int , int)),
this, SLOT(sourceRowsInserted(const QModelIndex &, int , int)));
connect(mSortFilterProxyModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex&, int)),
this, SLOT(sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex&, int)));
connect(mSortFilterProxyModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
this, SLOT(sourceRowsRemoved(const QModelIndex&, int, int)));
TX_EXIT
}
HgCacheProxyModel::~HgCacheProxyModel()
{
TX_ENTRY
delete mBufferManager;
TX_EXIT
}
void HgCacheProxyModel::setDataProvider(HgDataProviderModel *dataProvider, int cacheSize, int cacheTreshold)
{
TX_ENTRY
mDataProviderModel = dataProvider;
mSortFilterProxyModel->setSourceModel(mDataProviderModel);
if (mDataProviderModel){
mDataProviderModel->registerObserver(this);
mSupressBM = true;
resizeCache(cacheSize, cacheTreshold);
mSupressBM = false;
if (mBufferManager == NULL){
mBufferManager = new HgBufferManager(this, cacheSize, cacheTreshold, 0, count() );
} else {
mBufferManager->resetBuffer(0, count());
}
}
TX_EXIT
}
HgDataProviderModel* HgCacheProxyModel::DataProvider()
{
return mDataProviderModel;
}
void HgCacheProxyModel::resizeCache(int newSize, int newTreshold)
{
TX_ENTRY
if (mDataProviderModel)
mDataProviderModel->resizeQPixmapPool(newSize);
if (mBufferManager)
mBufferManager->resizeCache( newSize, newTreshold );
TX_EXIT
}
QModelIndex HgCacheProxyModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent);
if ( row >= rowCount() ){
row = -1;
}
if ( column >= columnCount() ){
column = -1;
}
return QAbstractItemModel::createIndex(row, column);
}
QModelIndex HgCacheProxyModel::parent(const QModelIndex &child) const
{
return mSortFilterProxyModel->parent(mapToSource(child));
}
int HgCacheProxyModel::rowCount(const QModelIndex &parent) const
{
return mSortFilterProxyModel->rowCount(mapToSource(parent));
}
int HgCacheProxyModel::columnCount(const QModelIndex &parent) const
{
return mSortFilterProxyModel->columnCount(mapToSource(parent));
}
bool HgCacheProxyModel::hasChildren(const QModelIndex &parent) const
{
return mSortFilterProxyModel->hasChildren(mapToSource(parent));
}
QVariant HgCacheProxyModel::data(const QModelIndex &index, int role) const
{
setBufferPosition(index.row());
QVariant res = mSortFilterProxyModel->data(mapToSource(index), role);
return res;
}
bool HgCacheProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
return mSortFilterProxyModel->setData(mapToSource(index), value, role);
}
QVariant HgCacheProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
return mSortFilterProxyModel->headerData(section, orientation, role);
}
bool HgCacheProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
{
return mSortFilterProxyModel->setHeaderData(section, orientation, value, role);
}
QMap<int, QVariant> HgCacheProxyModel::itemData(const QModelIndex &index) const
{
setBufferPosition(index.row());
return mSortFilterProxyModel->itemData(mapToSource(index));
}
bool HgCacheProxyModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
{
return mSortFilterProxyModel->setItemData(mapToSource(index), roles);
}
QStringList HgCacheProxyModel::mimeTypes() const
{
return mSortFilterProxyModel->mimeTypes();
}
QMimeData *HgCacheProxyModel::mimeData(const QModelIndexList &indexes) const
{
QModelIndexList list;
for ( int i=0; i < indexes.count(); i++){
list.append(mapToSource(indexes[i]));
}
return mSortFilterProxyModel->mimeData(list);
}
bool HgCacheProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
return mSortFilterProxyModel->dropMimeData(data, action, row, column, mapToSource(parent));
}
Qt::DropActions HgCacheProxyModel::supportedDropActions() const
{
return mSortFilterProxyModel->supportedDropActions();
}
bool HgCacheProxyModel::insertRows(int row, int count, const QModelIndex &parent)
{
return mSortFilterProxyModel->insertRows(row, count, mapToSource(parent));
}
bool HgCacheProxyModel::insertColumns(int column, int count, const QModelIndex &parent)
{
return mSortFilterProxyModel->insertColumns(column, count, mapToSource(parent));
}
bool HgCacheProxyModel::removeRows(int row, int count, const QModelIndex &parent)
{
return mSortFilterProxyModel->removeRows(row, count, mapToSource(parent));
}
bool HgCacheProxyModel::removeColumns(int column, int count, const QModelIndex &parent)
{
return mSortFilterProxyModel->removeColumns(column, count, mapToSource(parent));
}
void HgCacheProxyModel::fetchMore(const QModelIndex &parent)
{
mSortFilterProxyModel->fetchMore(mapToSource(parent));
}
bool HgCacheProxyModel::canFetchMore(const QModelIndex &parent) const
{
return mSortFilterProxyModel->canFetchMore(mapToSource(parent));
}
Qt::ItemFlags HgCacheProxyModel::flags(const QModelIndex &index) const
{
return mSortFilterProxyModel->flags(mapToSource(index));
}
void HgCacheProxyModel::sort(int column, Qt::SortOrder order)
{
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->sort(column, order);
resetBM();
}
QModelIndex HgCacheProxyModel::buddy(const QModelIndex &index) const
{
return mSortFilterProxyModel->buddy(mapToSource(index));
}
QModelIndexList HgCacheProxyModel::match(const QModelIndex &start, int role,
const QVariant &value, int hits,
Qt::MatchFlags flags) const
{
return mSortFilterProxyModel->match(mapToSource(start), role, value, hits, flags);
}
QSize HgCacheProxyModel::span(const QModelIndex &index) const
{
return mSortFilterProxyModel->span(mapToSource(index));
}
Qt::CaseSensitivity HgCacheProxyModel::sortCaseSensitivity() const
{
return mSortFilterProxyModel->sortCaseSensitivity();
}
void HgCacheProxyModel::setSortCaseSensitivity(Qt::CaseSensitivity cs)
{
if (sortCaseSensitivity() != cs){
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->setSortCaseSensitivity(cs);
resetBM();
}
}
bool HgCacheProxyModel::isSortLocaleAware() const
{
return mSortFilterProxyModel->isSortLocaleAware();
}
void HgCacheProxyModel::setSortLocaleAware(bool on)
{
if (isSortLocaleAware() != on){
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->setSortLocaleAware(on);
resetBM();
}
}
int HgCacheProxyModel::sortColumn() const
{
return mSortFilterProxyModel->sortColumn();
}
Qt::SortOrder HgCacheProxyModel::sortOrder() const
{
return mSortFilterProxyModel->sortOrder();
}
bool HgCacheProxyModel::dynamicSortFilter() const
{
return mSortFilterProxyModel->dynamicSortFilter();
}
void HgCacheProxyModel::setDynamicSortFilter(bool enable)
{
if (dynamicSortFilter() != enable){
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->setDynamicSortFilter(enable);
resetBM();
}
}
int HgCacheProxyModel::sortRole() const
{
return mSortFilterProxyModel->sortRole();
}
void HgCacheProxyModel::setSortRole(int role)
{
if (sortRole() != role){
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->setSortRole(role);
resetBM();
}
}
QRegExp HgCacheProxyModel::filterRegExp() const
{
return mSortFilterProxyModel->filterRegExp();
}
void HgCacheProxyModel::setFilterRegExp(const QRegExp ®Exp)
{
if (filterRegExp() != regExp){
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->setFilterRegExp(regExp);
resetBM();
}
}
int HgCacheProxyModel::filterKeyColumn() const
{
return mSortFilterProxyModel->filterKeyColumn();
}
void HgCacheProxyModel::setFilterKeyColumn(int column)
{
if (filterKeyColumn() != column){
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->setFilterKeyColumn(column);
resetBM();
}
}
Qt::CaseSensitivity HgCacheProxyModel::filterCaseSensitivity() const
{
return mSortFilterProxyModel->filterCaseSensitivity();
}
void HgCacheProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs)
{
if ( filterCaseSensitivity() != cs){
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->setFilterCaseSensitivity(cs);
resetBM();
}
}
int HgCacheProxyModel::filterRole() const
{
return mSortFilterProxyModel->filterRole();
}
void HgCacheProxyModel::setFilterRole(int role)
{
if ( filterRole() != role ){
mSupressBM = true;
cleanupForBMReset();
mSortFilterProxyModel->setFilterRole(role);
resetBM();
}
}
bool HgCacheProxyModel::submit()
{
return mSortFilterProxyModel->submit();
}
void HgCacheProxyModel::revert()
{
mSortFilterProxyModel->revert();
}
void HgCacheProxyModel::release(int start, int end)
{
TX_ENTRY_ARGS( QString("%0-%1").arg(start).arg(end));
QList<int> list;
int idx = 0;
if ( start > end){
idx = end;
end = start;
start = idx;
idx = 0;
}
for ( int i=start; i <=end; i++){
idx = mapToDataProviderIndex(i);
if ( idx >=0)
list.append(idx);
}
if (mDataProviderModel)
mDataProviderModel->release(list, true);
TX_EXIT
}
void HgCacheProxyModel::request(int start, int end, HgRequestOrder order)
{
TX_ENTRY_ARGS( QString("%0-%1").arg(start).arg(end));
QList<int> list;
int idx;
if (order == HgRequestOrderAscending){
for ( int i=start; i <=end; i++){
idx = mapToDataProviderIndex(i);
if ( idx >=0)
list.append(idx);
}
} else {
for ( int i=end; i >=start; i--){
idx = mapToDataProviderIndex(i);
if ( idx >=0)
list.append(idx);
}
}
if (mDataProviderModel)
mDataProviderModel->request(list, mSupressBM);
TX_EXIT
}
int HgCacheProxyModel::count()const
{
return rowCount(index(0, 0, QModelIndex()));
}
QModelIndex HgCacheProxyModel::mapToSource(const QModelIndex &index) const
{
return mapToSource(index.row(), index.column());
}
QModelIndex HgCacheProxyModel::mapToSource(int row, int col) const
{
return mSortFilterProxyModel->index(row, col);
}
int HgCacheProxyModel::mapToDataProviderIndex(int myIndex) const
{
return mSortFilterProxyModel->mapToSource( mapToSource(myIndex, 0)).row();
}
int HgCacheProxyModel::mapFromDataProviderIndex(int myIndex) const
{
return mSortFilterProxyModel->mapFromSource( mDataProviderModel->index(myIndex, 0) ).row();
}
void HgCacheProxyModel::cleanupForBMReset()
{
releaseAll();
}
void HgCacheProxyModel::resetBM()
{
if (mBufferManager){
mCurrentPos = 0;
mBufferManager->resetBuffer( mCurrentPos, count() );
}
mSupressBM = false;
}
void HgCacheProxyModel::releaseAll()
{
if ( mDataProviderModel ){
QList<int> list;
for ( int i=0; i<mDataProviderModel->rowCount(); i++){
list.append(i);
}
mDataProviderModel->release(list, true);
}
}
void HgCacheProxyModel::setBufferPosition(int pos) const
{
if (mBufferManager && !mSupressBM){
if (mCurrentPos!=pos){
// TX_LOG_ARGS(QString("pos:%1 ").arg(pos) );
mCurrentPos = pos;
mBufferManager->setPosition(mCurrentPos);
}
}
}
void HgCacheProxyModel::sourceColumnsAboutToBeInserted( const QModelIndex & parent, int start, int end)
{
TX_ENTRY
beginInsertColumns(parent, start, end);
TX_EXIT
}
void HgCacheProxyModel::sourceColumnsAboutToBeMoved( const QModelIndex & sourceParent, int sourceStart,
int sourceEnd, const QModelIndex & destinationParent, int destinationColumn )
{
TX_ENTRY
beginMoveColumns(sourceParent, sourceStart, sourceEnd, destinationParent, destinationColumn);
TX_EXIT
}
void HgCacheProxyModel::sourceColumnsAboutToBeRemoved( const QModelIndex & parent, int start, int end)
{
TX_ENTRY
beginRemoveColumns(parent, start, end);
TX_EXIT
}
void HgCacheProxyModel::sourceColumnsInserted( const QModelIndex & parent, int start, int end )
{
TX_ENTRY
Q_UNUSED(parent);
Q_UNUSED(start);
Q_UNUSED(end);
endInsertColumns();
TX_EXIT
}
void HgCacheProxyModel::sourceColumnsMoved( const QModelIndex & sourceParent, int sourceStart,
int sourceEnd, const QModelIndex & destinationParent, int destinationColumn )
{
TX_ENTRY
Q_UNUSED(sourceParent);
Q_UNUSED(sourceStart);
Q_UNUSED(sourceEnd);
Q_UNUSED(destinationParent);
Q_UNUSED(destinationColumn);
endMoveColumns();
TX_EXIT
}
void HgCacheProxyModel::sourceColumnsRemoved( const QModelIndex & parent, int start, int end )
{
TX_ENTRY
Q_UNUSED(parent);
Q_UNUSED(start);
Q_UNUSED(end);
endRemoveColumns();
TX_EXIT
}
void HgCacheProxyModel::sourceDataChanged( const QModelIndex & topLeft, const QModelIndex & bottomRight )
{
TX_ENTRY_ARGS(QString("from:%1 to:%2").arg( topLeft.row() ).arg( bottomRight.row() ) );
QModelIndex begin = index( topLeft.row(), topLeft.column() );
QModelIndex end = index( bottomRight.row(), bottomRight.column() );
if (begin.isValid() && end.isValid() && !mSupressBM)
emit dataChanged(begin, end);
TX_EXIT
}
void HgCacheProxyModel::sourceHeaderDataChanged( Qt::Orientation orientation, int first, int last )
{
TX_ENTRY
emit headerDataChanged( orientation, first, last );
TX_EXIT
}
void HgCacheProxyModel::sourceLayoutAboutToBeChanged()
{
TX_ENTRY
emit layoutAboutToBeChanged();
mSupressBM = true;
releaseAll();
TX_EXIT
}
void HgCacheProxyModel::sourceLayoutChanged()
{
TX_ENTRY
mSupressBM = true;
if (mBufferManager){
mCurrentPos = 0;
mBufferManager->resetBuffer( mCurrentPos, count() );
}
mSupressBM = false;
emit layoutChanged();
TX_EXIT
}
void HgCacheProxyModel::sourceModelAboutToBeReset()
{
TX_ENTRY
beginResetModel();
mSupressBM = true;
releaseAll();
TX_EXIT
}
void HgCacheProxyModel::sourceModelReset()
{
TX_ENTRY
mSupressBM = true;
if (mBufferManager){
mCurrentPos = 0;
mBufferManager->resetBuffer( mCurrentPos, count() );
}
mSupressBM = false;
endResetModel();
TX_EXIT
}
void HgCacheProxyModel::sourceRowsAboutToBeInserted( const QModelIndex & parent, int start, int end )
{
TX_ENTRY
if (mBufferManager && !mSupressBM){
beginInsertRows(parent, start, end);
// mBufferManager->aboutToInsertItems(start, end);
}
TX_EXIT
}
void HgCacheProxyModel::sourceRowsAboutToBeMoved( const QModelIndex & sourceParent, int sourceStart,
int sourceEnd, const QModelIndex & destinationParent, int destinationRow )
{
TX_ENTRY
beginMoveRows(sourceParent, sourceStart, sourceEnd, destinationParent, destinationRow);
TX_EXIT
}
void HgCacheProxyModel::sourceRowsAboutToBeRemoved( const QModelIndex & parent, int start, int end )
{
TX_ENTRY
if (mBufferManager && !mSupressBM){
beginRemoveRows(parent, start, end);
// mBufferManager->aboutToRemoveItems(start, end);
}
TX_EXIT
}
void HgCacheProxyModel::sourceRowsInserted( const QModelIndex & parent, int start, int end )
{
TX_ENTRY
Q_UNUSED(parent);
Q_UNUSED(end);
if (mBufferManager && !mSupressBM){
mBufferManager->itemCountChanged(start, false, count());
endInsertRows();
}
TX_EXIT
}
void HgCacheProxyModel::sourceRowsMoved( const QModelIndex & sourceParent, int sourceStart,
int sourceEnd, const QModelIndex & destinationParent, int destinationRow )
{
TX_ENTRY
Q_UNUSED(sourceParent);
Q_UNUSED(sourceStart);
Q_UNUSED(sourceEnd);
Q_UNUSED(destinationParent);
Q_UNUSED(destinationRow);
endMoveRows();
TX_EXIT
}
void HgCacheProxyModel::sourceRowsRemoved( const QModelIndex & parent, int start, int end )
{
TX_ENTRY
Q_UNUSED(parent);
Q_UNUSED(end);
if (mBufferManager && !mSupressBM){
mBufferManager->itemCountChanged(start, true, count());
endRemoveRows();
}
TX_EXIT
}
void HgCacheProxyModel::dataUpdated(int from, int to)
{
TX_LOG_ARGS(QString("from:%1 to:%2").arg(from).arg(to));
QModelIndex begin;
QModelIndex end;
begin = index(mapFromDataProviderIndex(from),0);
if ( from == to ){
end = begin;
} else {
end = index(mapFromDataProviderIndex(to),0);
}
if (begin.isValid() && end.isValid() && !mSupressBM)
emit dataChanged(begin, end );
}
//eof