/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "UBSceneCache.h" #include "domain/UBGraphicsScene.h" #include "core/UBPersistenceManager.h" #include "core/UBApplication.h" #include "core/UBSettings.h" #include "core/UBSetting.h" #include "document/UBDocumentProxy.h" #include "core/memcheck.h" UBSceneCache::UBSceneCache() : mCachedSceneCount(0) { // NOOP } UBSceneCache::~UBSceneCache() { // NOOP } UBGraphicsScene* UBSceneCache::createScene(UBDocumentProxy* proxy, int pageIndex) { UBGraphicsScene* newScene = new UBGraphicsScene(proxy); insert(proxy, pageIndex, newScene); return newScene; } void UBSceneCache::insert (UBDocumentProxy* proxy, int pageIndex, UBGraphicsScene* scene) { QList existingKeys = QHash::keys(scene); foreach(UBSceneCacheID key, existingKeys) { mCachedSceneCount -= QHash::remove(key); } UBSceneCacheID key(proxy, pageIndex); if (QHash::contains(key)) { QHash::insert(key, scene); mCachedKeyFIFO.enqueue(key); } else { if (mCachedSceneCount >= UBSettings::settings()->pageCacheSize->get().toInt()) { compactCache(); } QHash::insert(key, scene); mCachedKeyFIFO.enqueue(key); mCachedSceneCount++; } if (mViewStates.contains(key)) { scene->setViewState(mViewStates.value(key)); } } bool UBSceneCache::contains(UBDocumentProxy* proxy, int pageIndex) const { UBSceneCacheID key(proxy, pageIndex); return QHash::contains(key); } UBGraphicsScene* UBSceneCache::value(UBDocumentProxy* proxy, int pageIndex) { UBSceneCacheID key(proxy, pageIndex); if (QHash::contains(key)) { UBGraphicsScene* scene = QHash::value(key); mCachedKeyFIFO.removeAll(key); mCachedKeyFIFO.enqueue(key); return scene; } else { return 0; } } void UBSceneCache::removeScene(UBDocumentProxy* proxy, int pageIndex) { UBGraphicsScene* scene = value(proxy, pageIndex); if (scene && scene->views().size() == 0) { UBSceneCacheID key(proxy, pageIndex); int count = QHash::remove(key); mCachedKeyFIFO.removeAll(key); mViewStates.insert(key, scene->viewState()); scene->deleteLater(); mCachedSceneCount -= count; } } void UBSceneCache::removeAllScenes(UBDocumentProxy* proxy) { for(int i = 0 ; i < proxy->pageCount(); i++) { removeScene(proxy, i); } } void UBSceneCache::moveScene(UBDocumentProxy* proxy, int sourceIndex, int targetIndex) { UBSceneCacheID keySource(proxy, sourceIndex); UBGraphicsScene *scene = 0; if (QHash::contains(keySource)) { scene = QHash::value(keySource); mCachedKeyFIFO.removeAll(keySource); } if (sourceIndex < targetIndex) { for (int i = sourceIndex + 1; i <= targetIndex; i++) { internalMoveScene(proxy, i, i - 1); } } else { for (int i = sourceIndex - 1; i >= targetIndex; i--) { internalMoveScene(proxy, i, i + 1); } } UBSceneCacheID keyTarget(proxy, targetIndex); if (scene) { insert(proxy, targetIndex, scene); mCachedKeyFIFO.enqueue(keyTarget); } else if (QHash::contains(keyTarget)) { scene = QHash::take(keyTarget); mCachedKeyFIFO.removeAll(keyTarget); } } void UBSceneCache::shiftUpScenes(UBDocumentProxy* proxy, int startIncIndex, int endIncIndex) { for(int i = endIncIndex; i >= startIncIndex; i--) { internalMoveScene(proxy, i, i + 1); } } void UBSceneCache::internalMoveScene(UBDocumentProxy* proxy, int sourceIndex, int targetIndex) { UBSceneCacheID sourceKey(proxy, sourceIndex); if (QHash::contains(sourceKey)) { UBGraphicsScene* scene = QHash::take(sourceKey); mCachedKeyFIFO.removeAll(sourceKey); UBSceneCacheID targetKey(proxy, targetIndex); QHash::insert(targetKey, scene); mCachedKeyFIFO.enqueue(targetKey); } else { UBSceneCacheID targetKey(proxy, targetIndex); if (QHash::contains(targetKey)) { /*UBGraphicsScene* scene = */QHash::take(targetKey); mCachedKeyFIFO.removeAll(targetKey); } } } void UBSceneCache::compactCache() { bool foundUnusedScene = false; int count = 0; do { if (!mCachedKeyFIFO.isEmpty()) { const UBSceneCacheID nextKey = mCachedKeyFIFO.dequeue(); if (QHash::contains(nextKey)) { UBGraphicsScene* scene = QHash::value(nextKey); if (scene && scene->views().size() == 0) { removeScene(nextKey.documentProxy, nextKey.pageIndex); foundUnusedScene = true; } else { mCachedKeyFIFO.enqueue(nextKey); } } } count++; } while (!foundUnusedScene && count < mCachedKeyFIFO.size()); } void UBSceneCache::dumpCacheContent() { foreach(UBSceneCacheID key, keys()) { UBGraphicsScene *scene = 0; if (QHash::contains(key)) scene = QHash::value(key); int index = key.pageIndex; qDebug() << "UBSceneCache::dumpCacheContent:" << index << " : " << scene; } }