diff -r 89c329efa980 -r e48454f237ca hgcacheproxymodel/src/hgdataprovidermodel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgcacheproxymodel/src/hgdataprovidermodel.cpp Mon May 03 13:32:54 2010 +0300 @@ -0,0 +1,387 @@ +/* +* 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: 3 % +*/ +#include +#include +#include +#include +#include +#include +#include "hglogger.h" + + +const int KQPixmapCacheEmergencyBuffer = 5; + +HgDataProviderModel::HgDataProviderModel(QObject *parent) : + QAbstractItemModel(parent), + mCache(new QList*>()), + mCacheSize(0), + mUnallocatedPixmaps(0), + mObserver(0) +{ + TX_ENTRY + TX_EXIT +} + +HgDataProviderModel::~HgDataProviderModel() +{ + TX_ENTRY + clearCache(); + delete mCache; + qDeleteAll( mFreePixmaps.begin(), mFreePixmaps.end() ); + mFreePixmaps.clear(); + qDeleteAll( mUsedPixmaps.begin(), mUsedPixmaps.end() ); + mUsedPixmaps.clear(); + TX_EXIT +} + +void HgDataProviderModel::release(QList list, bool silent) +{ + TX_ENTRY + int i=0; + int min = count(); + int max = 0; + + for ( int idx = 0; idx < list.count(); idx++){ + i = list[idx]; + if ( i >=0 && i max) + max = i; + resetIcon(i); + } + } + + doReleaseData(list, silent); + + if (min list, bool silent) +{ + doRequestData(list, silent); +} + +void HgDataProviderModel::registerObserver(HgDataProviderModelObserver* obs) +{ + TX_ENTRY + mObserver = obs; + TX_EXIT +} + +QModelIndex HgDataProviderModel::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 HgDataProviderModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); //returns always invalid model index +} + +int HgDataProviderModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return count(); +} + +int HgDataProviderModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 1; +} + +QVariant HgDataProviderModel::data(const QModelIndex &index, int role) const +{ + return data(index.row(), role); +} + +QVariant HgDataProviderModel::data(int idx, int role) const +{ + QVariant res; + if ( containsRole(idx, role)){ + res = mCache->at(idx)->value(role); + } else if (role == Qt::DecorationRole ){ + res = defaultIcon(); + } + return res; +} + +QMap HgDataProviderModel::itemData(const QModelIndex &index) const +{ + QMap res; + if ( index.row()>=0 && index.row()(*mCache->at(index.row())); + } + return res; +} + +void HgDataProviderModel::clearCache() +{ + qDeleteAll( mCache->begin(), mCache->end() ); + mCache->clear(); +} + +int HgDataProviderModel::count() const +{ + return mCache->count(); +} + +bool HgDataProviderModel::update(int pos, QList< QPair< QVariant, int > >* list, bool silent) +{ + bool change(false); + if (list && list->count() && pos >=0 && posat(pos)) { + while(list->count()){ + QPair< QVariant, int > pair = list->takeFirst(); + change = update(pos, pair.first, pair.second, true)|change; + } + if ( !silent && change ){ + emitDataChanged(pos, pos, false); + } + } + return change; +} + +bool HgDataProviderModel::update(int pos, QVariant obj, int role, bool silent) +{ + bool change(false); + + if ( pos >=0 && posat(pos)){ + mCache->at(pos)->insert(role, obj); //this will remove old one if needed + change = true; + } + + if ( !silent && change ){ + emitDataChanged(pos, pos, false); + } + return change; +} + +bool HgDataProviderModel::updateIcon(int pos, QVariant obj, bool silent) +{ + if (obj.isValid()==false) + return false; + + bool change(false); + if ( pos >=0 && posat(pos)){ + mCache->at(pos)->insert(Qt::DecorationRole, obj); //will remove old if needed + change = true; + } + + if (!silent && change){ + TX_LOG + if ( mObserver){ + mObserver->dataUpdated(pos,pos); + } else { + QModelIndex topLeft = index(pos, 0); + QModelIndex bottomRight = index(pos, 0); + emit dataChanged(topLeft,bottomRight); + } + } + return change; +} + +void HgDataProviderModel::resetIcon(int pos) +{ + if ( containsRole(pos, Qt::DecorationRole)){ + mCache->at(pos)->remove(Qt::DecorationRole); + } +} + +void HgDataProviderModel::newItem(QList< QPair< QVariant, int > >* list, bool silent) +{ + insertItem(mCache->count(), list, silent); +} + +void HgDataProviderModel::newItem(QPair< QVariant, int > item, bool silent) +{ + insertItem(mCache->count(), item, silent); +} + +void HgDataProviderModel::insertItem(int pos, QList< QPair< QVariant, int > >* list, bool silent) +{ + doInsertItem(pos, list, silent); +} + +void HgDataProviderModel::insertItem(int pos, QPair< QVariant, int > item, bool silent) +{ + QList< QPair< QVariant, int > > list; + list.append(item); + doInsertItem(pos, &list, silent); +} + +void HgDataProviderModel::doInsertItem(int pos, QList< QPair< QVariant, int > >* list, bool silent) +{ + if (pos >mCache->count()){ + pos = mCache->count(); + } else if (pos <0){ + pos = 0; + } + + if ( !silent){ + beginInsertRows(QModelIndex(), pos, pos); + } + + mCache->insert(pos, new QMap()); + if (list && list->count()){ + update(pos, list, true); + } + + if ( !silent){ + endInsertRows(); + } +} + + +void HgDataProviderModel::removeItem(int pos) +{ + removeItems(pos, 1); +} + +void HgDataProviderModel::removeItems(int pos, int size) +{ + if (pos >mCache->count()) + return; + else if (pos <0){ + size = size + pos; //pos <0 + pos = 0; + } + + if (size >mCache->count()){ + size = mCache->count(); + } else if (size <0){ + return; + } + + beginRemoveRows(QModelIndex(),pos, pos+size-1); + for (int i=0; icount(); i++){ + mCache->removeAt(pos); + } + endRemoveRows(); +} + +void HgDataProviderModel::resetModel() +{ + beginResetModel(); + doResetModel(); + endResetModel(); +} + +void HgDataProviderModel::emitDataChanged(int from, int to, bool silent) +{ + if ( !silent ){ + TX_LOG + QModelIndex topLeft = index(from, 0); + QModelIndex bottomRight = index(to, 0); + emit dataChanged(topLeft,bottomRight); + } +} + +void HgDataProviderModel::resizeQPixmapPool(int newSize) +{ + mQPixmapsLock.lock(); + int currentSize = mFreePixmaps.count() + mUsedPixmaps.count(); + int diff = currentSize - newSize - KQPixmapCacheEmergencyBuffer; + mUnallocatedPixmaps = 0; + while (diff != 0){ + if (diff < 0){ + mUnallocatedPixmaps++; + diff++; + }else{ + if (mUnallocatedPixmaps>0){ + mUnallocatedPixmaps--; + } else if (mFreePixmaps.count()){ + mFreePixmaps.removeLast(); + } //else will be deleted with releasePixmap; + diff--; + } + } + mQPixmapsLock.unlock(); + mCacheSize = newSize; +} + +void HgDataProviderModel::releasePixmap(int idx) +{ + mQPixmapsLock.lock(); + if (mUsedPixmaps.contains(idx)){ + QPixmap* pix = mUsedPixmaps.take(idx); + if ( mFreePixmaps.count() + mUsedPixmaps.count() + mUnallocatedPixmaps> mCacheSize + KQPixmapCacheEmergencyBuffer){ + delete pix; //we have too many pixmaps + }else{ + mFreePixmaps.append(pix); + } + }else{ + TX_LOG_ARGS( QString("can't release pixmap for idx=%0").arg(idx)); + } + mQPixmapsLock.unlock(); +} + +QVariant HgDataProviderModel::createIcon(int index, QPixmap aPixmap) +{ + QPixmap* pix = getPixmap(index); + if (pix){ + if ( pix->pixmapData() ){ + pix->pixmapData()->fromImage(aPixmap.toImage(), Qt::AutoColor ); + } else { + *pix = aPixmap; + } + mQPixmapsLock.lock(); + mUsedPixmaps.insert(index, pix); + mQPixmapsLock.unlock(); + return HbIcon(QIcon(*pix)); + } + TX_EXIT_ARGS( QString("No pixmap avilable")); + return QVariant(); +} + +QPixmap* HgDataProviderModel::getPixmap(int idx) +{ + TX_ENTRY + QPixmap* res = NULL; + mQPixmapsLock.lock(); + if ( mUsedPixmaps.contains(idx)){ + res = mUsedPixmaps.take(idx);//let's just replace pixmapdata for that pixmap + } else { + if (!mFreePixmaps.isEmpty()){ + res = mFreePixmaps.takeFirst(); + }else if (mUnallocatedPixmaps){ + mUnallocatedPixmaps--; + res = new QPixmap(); + } else { + TX_LOG_ARGS(QString("no free pixmaps")); + } + } + mQPixmapsLock.unlock(); + TX_EXIT + return res; +} + +//eof