diff -r 000000000000 -r 16d8024aca5e src/hbservers/hbthemeserver/hbthemeserver_generic.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hbservers/hbthemeserver/hbthemeserver_generic.cpp Mon Apr 19 14:02:13 2010 +0300 @@ -0,0 +1,1314 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (developer.feedback@nokia.com) +** +** This file is part of the HbServers module of the UI Extensions for Mobile. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at developer.feedback@nokia.com. +** +****************************************************************************/ + +#include "hbthemeserver_generic_p_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "hbthemecommon_p.h" +#include "hbmemoryutils_p.h" +#include "hbthemeserverutils_p.h" +#include "hbiconcacheitemcreator_p.h" +#include "hbiconloader_p.h" +#include "hbcache_p.h" +#include "hbdeviceprofiledatabase_p.h" +#include "hbpixmapiconimpl_p.h" +#include "hbpixmapiconprocessor_p.h" +#include "hblayeredstyleloader_p.h" + +/*! + @hbserver + \class HbThemeServerPrivate + \brief HbThemeServerPrivate implements the theme server +*/ + +#ifdef THEME_SERVER_TRACES +extern QLabel *testLabel; +#endif + +// 5 MB GPU & CPU cache size +#define GPU_CACHE_SIZE 0x500000 +#define CPU_CACHE_SIZE 0x500000 + +/*! + \fn HbThemeServerPrivate::HbThemeServerPrivate() + Constructor + \a parent +*/ +#ifdef QT_DEBUG +HbThemeServerPrivate::HbThemeServerPrivate(QWidget *parent): QMainWindow(parent), server(new QLocalServer(this)) +#else +HbThemeServerPrivate::HbThemeServerPrivate(): server(new QLocalServer(this)) +#endif +{ + iThemeSelectionClient = 0; + sessionList.clear(); +#ifdef QT_DEBUG + setWindowTitle("Theme Server"); +#endif + // Using QScopedPointer so that it deallocates memory + // when std::badalloc exception occurs. + QScopedPointer tempIconCache(new HbIconDataCache()); + QScopedPointer tempCssCache(new HbCache()); + iconCache = tempIconCache.take(); + cssCache = tempCssCache.take(); + setMaxGpuCacheSize(GPU_CACHE_SIZE); + setMaxCpuCacheSize(CPU_CACHE_SIZE); +} + +/*! + \fn HbThemeServerPrivate::~HbThemeServerPrivate() + Destructor +*/ +HbThemeServerPrivate::~HbThemeServerPrivate() +{ + server->close(); + delete server; // Order of Deletion needs to be maintain ,as the QLocalServer should delete first before deleting Server data so All sessions will be cleanup first. + delete iconCache; + delete cssCache; +} + +/*! + \fn HbThemeServerPrivate::start() + start the themeserver +*/ +bool HbThemeServerPrivate::start() +{ + bool success = false; + if (!server->listen(THEME_SERVER_NAME)) { + qWarning("Unable to start the server: %s.", server->errorString().toLatin1().data()); +#if defined(Q_OS_LINUX) || defined(Q_OS_MAC) + if (server->serverError() == QAbstractSocket::AddressInUseError) { + qDebug() << "Trying to delete temporary file hbthemeserver"; + QFile::remove("/tmp/hbthemeserver"); + success = start(); + } +#endif + return success; + } +#ifdef QT_DEBUG + statusLabel.setText("Theme Server Started"); + setCentralWidget(&statusLabel); +#endif + connect(server, SIGNAL(newConnection()), this, SLOT(newClientConnected())); + success = true; + return success; +} + +/*! + \fn HbThemeServerPrivate::insertIconCacheItem() + Insert item into the icon cache + \a key denotes the unique identifier for the cache item that is to be inserted into the cache. + \a item denotes the cache item that is to be inserted +*/ +bool HbThemeServerPrivate::insertIconCacheItem(const HbIconKey &key, HbIconCacheItem *item) +{ + return (iconCache->insert(key, item)); +} + +/*! + \fn HbThemeServerPrivate::insertCssCacheItem() + Insert item into the css cache + \a key denotes the unique identifier for the cache item that is to be inserted into the cache. + \a item denotes the cache item that is to be inserted +*/ +bool HbThemeServerPrivate::insertCssCacheItem(const QString &key, HbCacheItem *item) +{ + return (cssCache->insert(key, item)); +} + +/*! + \fn HbThemeServerPrivate::iconCacheItem() + Find an item in the icon cache + \a key denotes the unique identifier for the cache item that is to be found in the cache. +*/ +HbIconCacheItem *HbThemeServerPrivate::iconCacheItem(const HbIconKey &key) +{ + return(iconCache->getCacheItem(key, false)); +} + +/*! + \fn HbThemeServerPrivate::cssCacheItem() + Find an item in the css cache + \a key denotes the unique identifier for the cache item that is to be found in the cache. +*/ +HbCacheItem *HbThemeServerPrivate::cssCacheItem(const QString &key) +{ + return(cssCache->cacheItem(key)); +} + +/*! + \fn HbThemeServerPrivate::setMaxGpuCacheSize() + Provides a mechanism for setting the Gpu cache limit + \a size denotes the cache limit in bytes e.g. size = 0x500000 +*/ +void HbThemeServerPrivate::setMaxGpuCacheSize(int size) +{ + iconCache->setMaxGpuCacheSize(size); +} + +/*! + \fn HbThemeServerPrivate::setMaxCpuCacheSize() + Provides a mechanism for setting the Cpu cache limit + \a size denotes the cache limit in bytes e.g. size = 0x500000 +*/ +void HbThemeServerPrivate::setMaxCpuCacheSize(int size) +{ + iconCache->setMaxCpuCacheSize(size); +} + +/*! + \fn HbThemeServerPrivate::removeIconCacheItem() + Remove an item from iconcache corresponding to key. + \a key denotes the unique identifier for the cache item that is to be removed from the cache. +*/ +void HbThemeServerPrivate::removeIconCacheItem(const HbIconKey &key) +{ + iconCache->remove(key); +} + +/*! + \fn HbThemeServerPrivate::removeCssCacheItem() + Remove item from css cache corresponding to key. + \a key denotes the unique identifier for the cache item that is to be removed from the cache. +*/ +void HbThemeServerPrivate::removeCssCacheItem(const QString &key) +{ + cssCache->remove(key); +} + +/*! + \fn HbThemeServerPrivate::clearIconCache() + Clears the icon cache +*/ +void HbThemeServerPrivate::clearIconCache() +{ + iconCache->clear(); +} + +/*! + \fn HbThemeServerPrivate::clearCssCache() + Clears the css cache +*/ +void HbThemeServerPrivate::clearCssCache() +{ + cssCache->clear(); +} + + +/*! + data.type = INVALID_FORMAT; + \fn HbThemeServerPrivate::handleThemeSelection() + Handle change of theme + \a newTheme +*/ +void HbThemeServerPrivate::handleThemeSelection(const QString &newTheme) +{ +#ifdef THEME_SERVER_TRACES + qDebug() << Q_FUNC_INFO << " theme=" << newTheme; +#endif + // Modify the QSettings to store the applied theme + QSettings settings(QLatin1String(ORGANIZATION), QLatin1String(THEME_COMPONENT)); + QString prevTheme = settings.value("currenttheme").toString(); + if (prevTheme == newTheme) { + // Theme did not change, return. + return; + } + QString cleanThemeName = newTheme.trimmed(); + settings.setValue("currenttheme", cleanThemeName); + settings.sync(); + HbThemeServerRequest requestType; + requestType = EThemeSelection; + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out << (int)requestType; + out << cleanThemeName; + writeToClients(block); +} + +/*! + \fn HbThemeServerPrivate::writeToClients() + Write to all clients + \a block +*/ +void HbThemeServerPrivate::writeToClients(QByteArray &block) +{ + HbThemeServerSession *session; +#ifdef THEME_SERVER_TRACES + qDebug() << Q_FUNC_INFO << "socketlist count: " << sessionList.count(); +#endif + foreach(session, sessionList) { + QLocalSocket * curSocket = session->clientConnection(); + if (iThemeSelectionClient != curSocket) { + curSocket->write(block); + } + } +} + +/*! + \fn HbThemeServerPrivate::setThemeSelectionClient() + Set the theme selection client + \a socket +*/ +void HbThemeServerPrivate::setThemeSelectionClient(QLocalSocket *socket) +{ + iThemeSelectionClient = socket; +} + +/*! + \fn HbThemeServerPrivate::newClientConnected() + Creates a new session with the server. +*/ +void HbThemeServerPrivate::newClientConnected() +{ + QLocalSocket * newClient = server->nextPendingConnection(); + if (newClient) { + HbThemeServerSession * newSession = + new HbThemeServerSession(newClient, this); + // Store list of client connected to server + sessionList.append(newSession); +#ifdef THEME_SERVER_TRACES + qDebug() << "Total No of Connection after addition = " << sessionList.count(); +#endif + connect(newClient, SIGNAL(disconnected()), this, SLOT(removeFromList())); + } +} + +/*! + \fn HbThemeServerPrivate::removeFromList() + Remove a session from list +*/ +void HbThemeServerPrivate::removeFromList() +{ + QList::const_iterator itEnd(sessionList.constEnd()); + + for (QList::const_iterator iter = sessionList.constBegin(); + iter != itEnd; + ++iter) { + if ((*iter)->clientConnection() == (QLocalSocket *)sender()) { + sessionList.removeOne((*iter)); + delete(*iter); + break; + } + } + qDebug() << "Total No of Connection after deletion = " << sessionList.count(); +} + +//Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG +int HbThemeServerPrivate ::cacheIconCount() const +{ + return iconCache->count(); +} + +int HbThemeServerPrivate::freeVectorMemory() +{ + return iconCache->freeVectorMemory(); +} + +int HbThemeServerPrivate::freeRasterMemory() +{ + return iconCache->freeRasterMemory(); +} + +int HbThemeServerPrivate::lastAddedRefCount() +{ + return iconCache->lastAddedRefCount(); +} + +int HbThemeServerPrivate::lastAddedItemMem() +{ + return iconCache->lastAddedItemMem(); +} + +int HbThemeServerPrivate::lastRemovedItemMem() +{ + return iconCache->lastRemovedItemMem(); +} + +int HbThemeServerPrivate::lastRemovedItemRfCount() +{ + return iconCache->lastRemovedItemRfCount(); +} + +bool HbThemeServerPrivate::enableCache(bool cacheIt) +{ + return iconCache->enableCache(cacheIt); +} + +int HbThemeServerPrivate::cacheHitCount() +{ + return iconCache->cacheHitCount(); +} + +int HbThemeServerPrivate::cacheMissCount() +{ + return iconCache->cacheMissCount(); +} + +int HbThemeServerPrivate::serverHeapSize() +{ + return 0; +} + +void HbThemeServerPrivate::cleanVectorLRUList() +{ + iconCache->cleanVectorLRUList(); +} + +void HbThemeServerPrivate::cleanRasterLRUList() +{ + iconCache->cleanRasterLRUList(); +} + +int HbThemeServerPrivate::rasterLruCount() +{ + return iconCache->rasterLruCount(); +} + +int HbThemeServerPrivate::vectorLruCount() +{ + return iconCache->vectorLruCount(); +} +#endif + +//*********************************** +//HbThemeServerSession - implementations +//*********************************** +/*! + @hbserver + \class HbThemeServerSession + \brief HbThemeServerSession implements the sessions associated with the server. + The Theme server maintains a list of sessions, each session corresponding to a client. + Each session in turn is responsible for keeping track of client specific resources. + In case of Icon caching, a session maintains a list of Icon keys. + A key is added to the list only if the corresponding cache item has been successfully inserted into cache + or if a previously cached icon is requested and successfully found in the cache. + In case of client crash or graceful exit of client, the server goes through its list of sessions, + finds the session corresponding to the client, removes the session from its session list and deletes the session. + In the session destructor, the session specific resources are cleaned up. + In case of icon caching, the list of icon keys is traversed and a remove operation is performed on the cache + items corresponding to these keys. On removal, the items reference count is decremented and in case the + reference count becomes 0, the cache item instance gets added to the back of the LRU list. + +*/ + +/*! + \fn HbThemeServerSession::HbThemeServerSession() + Constructor + \a aClientConnection indicates the local socket that is contained within this session + \a aServer denotes the handle to the theme server +*/ +HbThemeServerSession::HbThemeServerSession(QLocalSocket *aClientConnection, HbThemeServerPrivate *aServer) +{ + iServer = aServer; + iClientConnection = aClientConnection; + sessionIconData.clear(); + sessionCssData.clear(); + connect(iClientConnection, SIGNAL(readyRead()), this, SLOT(readDataFromClient())); + connect(iClientConnection, SIGNAL(disconnected()), iClientConnection, SLOT(deleteLater())); +} + +/*! + \fn HbThemeServerSession::~HbThemeServerSession() + Destructor +*/ +HbThemeServerSession::~HbThemeServerSession() +{ + //Remove icon related-session-specific data + QList::const_iterator itEnd(sessionIconData.constEnd()); + for (QList::const_iterator iter = sessionIconData.constBegin(); + iter != itEnd; + ++iter) { + iServer->removeIconCacheItem(*iter); + } + + //Remove css related-session-specific data + QList::const_iterator iterEnd(sessionCssData.constEnd()); + for (QList::const_iterator iter = sessionCssData.constBegin(); + iter != iterEnd; + ++iter) { + iServer->removeCssCacheItem(*iter); + } + sessionIconData.clear(); + sessionCssData.clear(); +} + +/*! + \fn HbThemeServerSession::clientConnection() + Returns a handle to the local socket contained by the session +*/ +QLocalSocket * HbThemeServerSession::clientConnection() +{ + return iClientConnection; +} + +/*! + \fn HbThemeServerSession::readDataFromClient() + Slot that is reponsible for reading data from the client + Is responsible for performing operations such as creating cache items and storing into cache + and writing back data to the client +*/ +void HbThemeServerSession::readDataFromClient() +{ +#ifdef THEME_SERVER_TRACES + qDebug() << Q_FUNC_INFO; +#endif + HbSharedIconInfo data; + data.type = INVALID_FORMAT; + HbThemeServerRequest requestType; + QByteArray inputByteArray = ((QLocalSocket *)sender())->readAll(); + if (inputByteArray.size() > 0) { + QDataStream inputDataStream(inputByteArray); + int clue; + inputDataStream >> clue; + requestType = (HbThemeServerRequest)clue; + +#ifdef THEME_SERVER_TRACES + qDebug() << Q_FUNC_INFO << "recognizer: " << requestType; +#endif + +//Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + QByteArray outputByteArray; + QDataStream outputDataStream(&outputByteArray, QIODevice::WriteOnly); + outputDataStream << (int)requestType; +#endif + switch (requestType) { + case EStyleSheetLookup: { + QString fileName; + int priority; + HbLayeredStyleLoader::LayerPriority layerdPriority; + inputDataStream >> fileName; + inputDataStream >> priority; + layerdPriority = (HbLayeredStyleLoader::LayerPriority) priority; + QByteArray output = handleStyleSheetLookup((int) requestType, fileName, layerdPriority); + ((QLocalSocket *)sender())->write(output); + break; + } + case EWidgetMLLookup: { + QString filename; + QString section; + QString layout; + + inputDataStream >> filename; + inputDataStream >> layout; + inputDataStream >> section; + // handle the shared Widgetml look up. + QByteArray output = iServer->handleSharedWidgetMLLookup(filename, layout, section); + ((QLocalSocket *)sender())->write(output); + break; + } + case EDeviceProfileOffset: { + int offset = -1; + HbDeviceProfileDatabase *deviceProfileDatabase = + HbDeviceProfileDatabase::instance(HbMemoryManager::SharedMemory); + + if (deviceProfileDatabase) { + offset = deviceProfileDatabase->deviceProfilesOffset(); + } + // offset will be -1 if the deviceProfileDatabase is NULL. + QByteArray outputByteArray; + QDataStream outputDataStream(&outputByteArray, QIODevice::WriteOnly); + outputDataStream << requestType; + outputDataStream << offset; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ESecondaryCacheOffset: { + int offset = HbThemeServerUtils::sharedCacheOffset(); + QByteArray outputByteArray; + QDataStream outputDataStream(&outputByteArray, QIODevice::WriteOnly); + outputDataStream << requestType; + outputDataStream << offset; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case EEffectLookupFilePath: + case EEffectAdd: { + QString fileName; + inputDataStream >> fileName; + QByteArray output = iServer->handleSharedEffectAddAndFileLookup((int) requestType, fileName); + ((QLocalSocket *)sender())->write(output); + break; + } + case EThemeSelection: { + QString themename; + QLocalSocket *themeSelectionClient = (QLocalSocket *)sender(); + inputDataStream >> themename; + iServer->setThemeSelectionClient(themeSelectionClient); + iServer->handleThemeSelection(themename); + break; + } + case EThemeContentUpdate: { + iServer->clearIconCache(); + HbThemeServerRequest requestType = EThemeContentUpdate; + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out << (int)requestType; + iServer->writeToClients(block); + break; + } + case EThemeServerStop: { + //This segment is used by HbThemeApiWrapperUi. + //When no HbApplication is open and HbThemeserver has only HbThemeApiWrapperUi as client, making sessionListCount =1 + //HbThemeserver is closed otherwise warning is shown. + //QCoreApplication::quit() removes the UI of HbThemeServer. Destructor of HbThemeServer will be called where it was instantiated. + if (iServer->sessionListCount() == 1) { +#ifdef QT_DEBUG + iServer->close(); +#endif + ((QLocalSocket *)sender())->disconnectFromServer(); + QCoreApplication::quit(); + } else { + qWarning() << "Close all HbApplications before closing hbthemeserver!!"; + } + break; + } + case EIconLookup: { + QString filename; + QSizeF size; + int aspectRatioMode; + int mode; + bool mirrored; + int options; + QColor color; + inputDataStream >> filename; + inputDataStream >> size; + inputDataStream >> aspectRatioMode; + inputDataStream >> mode; + inputDataStream >> mirrored; + inputDataStream >> options; + inputDataStream >> color; + +#ifdef THEME_SERVER_TRACES + qDebug() << "image req at server: " << filename; +#endif + HbIconKey key(filename, size, (Qt::AspectRatioMode)aspectRatioMode, (QIcon::Mode)mode, mirrored, color); + QByteArray output = handleIconLookup(key, data, options); + ((QLocalSocket *)sender())->write(output); + break; + } + case EIconDefaultSize: + break; //todo + case EMultiPieceIcon: { + HbMultiIconParams frameItemParams; + inputDataStream >> frameItemParams.multiPartIconList; + inputDataStream >> frameItemParams.multiPartIconData.multiPartIconId; + + int noOfPieces = 1; + if (frameItemParams.multiPartIconData.multiPartIconId.contains("_3PV", Qt::CaseInsensitive) || + frameItemParams.multiPartIconData.multiPartIconId.contains("_3PH", Qt::CaseInsensitive)) { + noOfPieces = 3; + } else if (frameItemParams.multiPartIconData.multiPartIconId.contains("_9P", Qt::CaseInsensitive)) { + noOfPieces = 9; + } + + for (int i = 0; i < noOfPieces; i++) { + inputDataStream >> frameItemParams.multiPartIconData.sources[i]; + } + + for (int i = 0; i < noOfPieces; i++) { + inputDataStream >> frameItemParams.multiPartIconData.targets[i]; + } + + for (int i = 0; i < noOfPieces; i++) { + inputDataStream >> frameItemParams.multiPartIconData.pixmapSizes[i]; + } + + inputDataStream >> frameItemParams.size; + inputDataStream >> frameItemParams.aspectRatioMode; + inputDataStream >> frameItemParams.mode; + inputDataStream >> frameItemParams.mirrored; + inputDataStream >> frameItemParams.options; + inputDataStream >> frameItemParams.color; + +#ifdef THEME_SERVER_TRACES + qDebug() << "image req at server: " << frameItemParams.multiPartIconList; +#endif + + int index = frameItemParams.multiPartIconList[0].lastIndexOf("/"); + QString iconId = frameItemParams.multiPartIconList[0].left(index + 1); + HbSharedIconInfo stitchedData; + QT_TRY { + iconId.append(frameItemParams.multiPartIconData.multiPartIconId); + HbIconKey finalIconKey(iconId, frameItemParams.size, + (Qt::AspectRatioMode)frameItemParams.aspectRatioMode, + (QIcon::Mode)frameItemParams.mode, frameItemParams.mirrored, + frameItemParams.color); + + stitchedData.type = INVALID_FORMAT; + + if (!iconInfoFromSingleIcon(finalIconKey, stitchedData)) { + iconInfoFromMultiParts(frameItemParams, noOfPieces, finalIconKey, stitchedData); + } + } QT_CATCH(const std::bad_alloc &) { + stitchedData.type = INVALID_FORMAT; + } + + QByteArray outputByteArray; + QDataStream outputDataStream(&outputByteArray, QIODevice::WriteOnly); + HbThemeServerRequest request; + request = EMultiPieceIcon; + fillOutPutDataStream(outputDataStream, stitchedData, request); +#ifdef THEME_SERVER_TRACES + qDebug() << Q_FUNC_INFO << " offset= " << stitchedData.pixmapData.offset << " format= " << stitchedData.pixmapData.format; + testLabel->setPixmap(QPixmap::fromImage( + QImage( + HbMemoryUtils::getAddress(HbMemoryManager::SharedMemory, stitchedData.pixmapData.offset), + stitchedData.pixmapData.width, + stitchedData.pixmapData.height, + stitchedData.pixmapData.format))); +#endif + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case EMultiIcon: { + QStringList fileList; + QVector sizeList; + QSizeF size; + int aspectRatioMode; + int mode; + bool mirrored; + int options; + QColor color; + inputDataStream >> fileList; + for (int i = 0; i < fileList.count(); i++) { + inputDataStream >> size; + sizeList << size; + } + inputDataStream >> aspectRatioMode; + inputDataStream >> mode; + inputDataStream >> mirrored; + inputDataStream >> options; + inputDataStream >> color; + +#ifdef THEME_SERVER_TRACES + qDebug() << "image req at server: " << filename; +#endif + QByteArray output; + for (int i = 0; i < fileList.count(); i++) { + HbIconKey key(fileList[i], sizeList[i], (Qt::AspectRatioMode)aspectRatioMode, (QIcon::Mode)mode, mirrored, color); + output.append(handleIconLookup(key, data, options)); + } + + ((QLocalSocket *)sender())->write(output); + + break; + } + //Debug Code for Test Purpose +#ifdef HB_ICON_CACHE_DEBUG + case ECacheIconCount: { + int count = iServer->cacheIconCount(); + outputDataStream << count; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ERasterMemLimit: { + int limit; + inputDataStream >> limit; + iServer->setMaxGpuCacheSize(limit); + break; + } + case EVectorMemLimit: { + int limit; + inputDataStream >> limit; + iServer->setMaxCpuCacheSize(limit); + break; + } + case EFreeRasterMem: { + int freeRastMem = iServer->freeRasterMemory(); + outputDataStream << freeRastMem; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case EFreeVectorMem: { + int freeVectMem = iServer->freeVectorMemory(); + outputDataStream << freeVectMem; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ELastAddedItemMem { + int lAddItemMem = iServer->lastAddedItemMem(); + outputDataStream << lAddItemMem; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ELastRemovedItemMem { + int lRemItemMem = iServer->lastRemovedItemMem(); + outputDataStream << lRemItemMem; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ELastRemovedItemRefCount: { + int lRemItemRfCnt = iServer->lastRemovedItemRfCount(); + outputDataStream << lRemItemRfCnt; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ELastAddedItemRefCount: { + int lAddItemRfCnt = iServer->lastAddedRefCount(); + outputDataStream << lAddItemRfCnt; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case EEnableCache: { + int enable ; + inputDataStream >> enable; + bool success = iServer->enableCache(enable); + outputDataStream << (int)success; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ECacheHit: { + int cacheHitCnt = iServer->cacheHitCount(); + outputDataStream << cacheHitCnt; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ECacheMiss: { + int cacheMissCnt = iServer->cacheMissCount(); + outputDataStream << cacheMissCnt; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ECleanRasterLRUList: { + iServer->cleanRasterLRUList(); + break; + } + case ECleanVectorLRUList: { + iServer->cleanVectorLRUList(); + break; + } + case EGpuLruCount: { + int rasterLruCount = iServer->rasterLruCount(); + outputDataStream << rasterLruCount; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case ECpuLruCount: { + int vectorLruCount = iServer->vectorLruCount(); + outputDataStream << vectorLruCount; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + case EServerHeap: { + } +#endif + case EUnloadIcon: { + QString filename; + QSizeF size; + int aspectRatioMode; + int mode; + bool mirrored; + int options; + QColor color; + inputDataStream >> filename; + inputDataStream >> size; + inputDataStream >> aspectRatioMode; + inputDataStream >> mode; + inputDataStream >> mirrored; + inputDataStream >> options; + inputDataStream >> color; + + HbIconKey key(filename, size, (Qt::AspectRatioMode)aspectRatioMode, + (QIcon::Mode)mode, mirrored, color); + iServer->removeIconCacheItem(key); + sessionIconData.removeOne(key); + QByteArray outputByteArray; + QDataStream outputDataStream(&outputByteArray, QIODevice::WriteOnly); + outputDataStream << (int)requestType; + ((QLocalSocket *)sender())->write(outputByteArray); + break; + } + default: + break; + } + } +} + +/*! + \fn HbThemeServerSession::iconInfoFromSingleIcon() + Checks for the cacheItem for a given key, if found gets the data relevant of the cacheItem. +*/ + +bool HbThemeServerSession::iconInfoFromSingleIcon(HbIconKey key, + HbSharedIconInfo &stitchedData) +{ + stitchedData.type = INVALID_FORMAT; + HbIconCacheItem * cacheItem = iServer->iconCacheItem(key); + if (cacheItem) { + getDataFromCacheItem(cacheItem, stitchedData); + return true; + } + return false; +} + +/*! + \fn HbThemeServerSession::createCacheItemData() + Creates a cacheItem of the given key and insert the item in to the list + else free the data allocated for the cache.. +*/ +bool HbThemeServerSession::createCacheItemData(HbIconKey key, int options , HbSharedIconInfo &data) +{ + HbIconCacheItem * cacheItemOfPiece = iServer->iconCacheItem(key); + if (cacheItemOfPiece) { + return true; + } + + QScopedPointer tempIconCacheItem; + bool insertKeyIntoSessionList = false; + data.type = INVALID_FORMAT; + QString format = HbThemeServerUtils::formatFromPath(key.filename); + + tempIconCacheItem.reset(HbIconCacheItemCreator::createCacheItem(key, + (HbIconLoader::IconLoaderOptions)options, + format, + false)); + cacheItemOfPiece = tempIconCacheItem.data(); + if (cacheItemOfPiece) { + getDataFromCacheItem(cacheItemOfPiece, data); + if (data.type != INVALID_FORMAT) { + insertKeyIntoSessionList = iServer->insertIconCacheItem(key, cacheItemOfPiece); + if (!insertKeyIntoSessionList) { + //if insertion failed free the memory + freeDataFromCacheItem(cacheItemOfPiece); + data.type = INVALID_FORMAT; + } + } + } + tempIconCacheItem.take(); + return insertKeyIntoSessionList; +} + +/*! + \fn HbThemeServerSession::createStichedIconInfoOfParts() + Creates a consolidated icon of the available piece iconInfo. +*/ +bool HbThemeServerSession::createStichedIconInfoOfParts(QVector dataForParts, HbMultiIconParams params, + HbIconKey &finalIconKey, HbSharedIconInfo &stitchedData) +{ + HbIconCacheItem * cacheItem = iServer->iconCacheItem(finalIconKey); + if (cacheItem) { + return true; + } + bool insertKeyIntoSessionList = false; + stitchedData.type = INVALID_FORMAT; + QString format = HbThemeServerUtils::formatFromPath(params.multiPartIconList[0]); + + QScopedPointer tempIconProcessor(new HbPixmapIconProcessor(finalIconKey, (HbIconLoader::IconLoaderOptions)params.options, format)); + HbPixmapIconProcessor * rasterIcon = tempIconProcessor.data(); + rasterIcon->createMultiPieceIconData(dataForParts, params); + + QScopedPointer tempIconCacheItem; + tempIconCacheItem.reset(HbIconCacheItemCreator::createCacheItem(finalIconKey, (HbIconLoader::IconLoaderOptions)params.options, format, false)); + cacheItem = tempIconCacheItem.data(); + + cacheItem->rasterIconData = rasterIcon->sharedIconData(); + cacheItem->rasterIconDataCost = rasterIcon->sharedIconDataCost(); + stitchedData = cacheItem->rasterIconData; + if (stitchedData.type != INVALID_FORMAT) { + insertKeyIntoSessionList = iServer->insertIconCacheItem(finalIconKey, cacheItem); + if (!insertKeyIntoSessionList) { + //if insertion failed free the memory + freeDataFromCacheItem(cacheItem); + stitchedData.type = INVALID_FORMAT; + } + } + tempIconCacheItem.take(); + delete rasterIcon; + return insertKeyIntoSessionList; +} + + +/*! + \fn HbThemeServerSession::iconInfoFromMultiParts() + Creates a shared IconInfo of the piece files of a frame item and + tries to create a stiched icon of the same. +*/ +void HbThemeServerSession::iconInfoFromMultiParts(HbMultiIconParams params, + int noOfPieces, + HbIconKey &stichedKey, + HbSharedIconInfo &stitchedData) +{ + QVector keysInserted; + QVector dataForParts; + bool insertKeyIntoSessionList = false; + bool failedToCreateParts = false; + QString format; + + + for (int i = 0; i < noOfPieces; i++) { + HbSharedIconInfo data; + bool iconPieceMirrored = false; + HbIconKey key(params.multiPartIconList.at(i), params.multiPartIconData.pixmapSizes[i], (Qt::AspectRatioMode)stichedKey.aspectRatioMode, (QIcon::Mode)stichedKey.mode, iconPieceMirrored, stichedKey.color); + insertKeyIntoSessionList = iconInfoFromSingleIcon(key, data); + if (!insertKeyIntoSessionList) { + insertKeyIntoSessionList = createCacheItemData(key, params.options, data); + } + if ((data.type == INVALID_FORMAT) || (!insertKeyIntoSessionList)) { + failedToCreateParts = true; + break; + } else { + //The session will only keep track of icons that were either successfully found or were + //successfully inserted in the cache. + keysInserted.append(key); + dataForParts.append(data); + sessionIconData.append(key); + } + }//end of for + + if ((failedToCreateParts) || (dataForParts.count() != noOfPieces) || (!insertKeyIntoSessionList)) { + //atLeast one of the icon did'nt get constructed , so move the cached piece icons to unused state and return + for (int i = 0; i < keysInserted.count(); i++) { + sessionIconData.removeOne(keysInserted.at(i)); + } + dataForParts.clear(); + stitchedData.type = INVALID_FORMAT; + return; + } +// Create a stitched icon of the available piece shared iconinfos + if ((dataForParts.count() == noOfPieces) && (!failedToCreateParts)) { + if (createStichedIconInfoOfParts(dataForParts, params, stichedKey, stitchedData)) { + sessionIconData.append(stichedKey); + } + } +// Move the keys created for pieces to unused state*/ + for (int i = 0; i < keysInserted.count(); i++) { + sessionIconData.removeOne(keysInserted.at(i)); + } +} + +/*! + \fn HbThemeServerSession::freeDataFromCacheItem() + Frees data from the cached item when insertion to the list fails. +*/ +void HbThemeServerSession::freeDataFromCacheItem(HbIconCacheItem* cacheItem) +{ + GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory) + if (cacheItem->rasterIconData.type != INVALID_FORMAT) { + switch (cacheItem->rasterIconData.type) { + case PIC : + manager->free(cacheItem->rasterIconData.picData.offset); + break; + case NVG : + manager->free(cacheItem->rasterIconData.nvgData.offset); + break; + case OTHER_SUPPORTED_FORMATS : + manager->free(cacheItem->rasterIconData.pixmapData.offset); + break; + default: + break; + } + } + if (cacheItem->vectorIconData.type != INVALID_FORMAT) { + switch (cacheItem->vectorIconData.type) { + case PIC : + manager->free(cacheItem->vectorIconData.picData.offset); + break; + case NVG : + manager->free(cacheItem->vectorIconData.nvgData.offset); + break; + case OTHER_SUPPORTED_FORMATS : + manager->free(cacheItem->vectorIconData.pixmapData.offset); + break; + default: + break; + } + } + if (cacheItem->blobIconData.type == BLOB) { + manager->free(cacheItem->blobIconData.blobData.offset); + } +} + +/*! + \fn HbThemeServerSession::fillOutPutDataStream() + Fills the Output data stream with the sharedIconInfo data. +*/ +void HbThemeServerSession::fillOutPutDataStream(QDataStream &outputDataStream, HbSharedIconInfo &data, HbThemeServerRequest request) +{ + outputDataStream << (int)request; + outputDataStream << (int)data.type; + + switch (data.type) { + case OTHER_SUPPORTED_FORMATS: + outputDataStream << data.pixmapData.offset; + outputDataStream << data.pixmapData.width; + outputDataStream << data.pixmapData.height; + outputDataStream << data.pixmapData.defaultWidth; + outputDataStream << data.pixmapData.defaultHeight; + outputDataStream << (int)data.pixmapData.format; + break; + /*case SVG:*/ + case PIC: { + outputDataStream << data.picData.offset; + outputDataStream << data.picData.dataSize; + outputDataStream << data.picData.defaultWidth; + outputDataStream << data.picData.defaultHeight; + break; + } + case NVG: { + outputDataStream << data.nvgData.offset; + outputDataStream << data.nvgData.dataSize; + break; + } + case BLOB: { + outputDataStream << data.blobData.offset; + outputDataStream << data.blobData.dataSize; + break; + } + default: + break; + } +} + +/*! + \fn HbThemeServerSession::getDataFromCacheItem() + Gets data from the cache Item. +*/ +void HbThemeServerSession::getDataFromCacheItem(HbIconCacheItem* cacheItem, HbSharedIconInfo &data) const +{ + if (cacheItem) { + if (cacheItem->rasterIconData.type != INVALID_FORMAT) { + data = cacheItem->rasterIconData; + } else if (cacheItem->vectorIconData.type != INVALID_FORMAT) { + data = cacheItem->vectorIconData; + } else if (cacheItem->blobIconData.type != INVALID_FORMAT) { + data = cacheItem->blobIconData; + } else { + data.type = INVALID_FORMAT; + } + } +} + +/** + * HbThemeServerPrivate::handleSharedWidgetMLLookup() + */ +QByteArray HbThemeServerPrivate::handleSharedWidgetMLLookup(const QString &fileName, const QString &layout, const QString §ion) +{ + int offset = HbThemeServerUtils::getSharedLayoutDefinition(fileName, layout, section); + QByteArray outputByteArray; + QDataStream outputDataStream(&outputByteArray, QIODevice::WriteOnly); + HbThemeServerRequest request; + request = EWidgetMLLookup; + outputDataStream << (int)request; + outputDataStream << offset; + return outputByteArray; +} + +/** + * HbThemeServerPrivate::handleSharedEffectAddAndFileLookup() + */ +QByteArray HbThemeServerPrivate::handleSharedEffectAddAndFileLookup(int request, const QString &fileName) +{ + int offset = HbThemeServerUtils::getSharedEffect(fileName); + QByteArray outputByteArray; + QDataStream outputDataStream(&outputByteArray, QIODevice::WriteOnly); + outputDataStream << request; + outputDataStream << offset; + return outputByteArray; +} + +/** + * HbThemeServerSession::handleStyleSheetLookup() + */ +QByteArray HbThemeServerSession::handleStyleSheetLookup(int request, const QString &fileName, HbLayeredStyleLoader::LayerPriority priority) +{ + int offset = -1; + HbCacheItem* cssItem = iServer->cssCacheItem(fileName); + bool insertKeyIntoSessionList = false; + if (cssItem) { + offset = cssItem->offset; + insertKeyIntoSessionList = true; + } else { + bool tryAgain = false; + do { + offset = HbThemeServerUtils::getSharedStylesheet(fileName, priority); + if (offset >= 0) { + HbCacheItem *cssItem = new HbCacheItem(offset, 0, fileName); + insertKeyIntoSessionList = iServer->insertCssCacheItem(fileName, cssItem); + if (priority == HbLayeredStyleLoader::Priority_Core && cssItem->refCount == 1) { + // This will make sure the requested stylesheet will always remain + // in the primary and secondary cache. + cssItem->incrementRefCount(); + } + break; + } else if (offset == OUT_OF_MEMORY_ERROR && tryAgain == false) { + iServer->doCleanup(); + tryAgain = true; + } else if (offset == OUT_OF_MEMORY_ERROR && tryAgain == true) { + //try only once to free up memory, else offset remains -2 + tryAgain = false; + } + } while (tryAgain); + } + + if (insertKeyIntoSessionList) { + //The session will only keep track of cssFiles that were either successfully found or were + //successfully inserted in the cache. + sessionCssData.append(fileName); + } + + //write to client socket the offset of required stylesheet + //it can be -1 in case of error. + QByteArray output; + QDataStream outputDataStream(&output, QIODevice::WriteOnly); + + outputDataStream << request; + outputDataStream << offset; + + return output; +} + +/** + * HbThemeServerSession::handleIconLookup() + */ +QByteArray HbThemeServerSession::handleIconLookup(const HbIconKey &key, HbSharedIconInfo &data, int options) +{ + bool insertKeyIntoSessionList = false; + HbIconCacheItem * cacheItem = iServer->iconCacheItem(key); + QScopedPointer tempIconCacheItem; + + if (cacheItem) { + insertKeyIntoSessionList = true; //The item was found in the cache and ref count was incremented + if (cacheItem->rasterIconData.type != INVALID_FORMAT) { + data = cacheItem->rasterIconData; + } else if (cacheItem->vectorIconData.type != INVALID_FORMAT) { + data = cacheItem->vectorIconData; + } else if (cacheItem->blobIconData.type != INVALID_FORMAT) { + data = cacheItem->blobIconData; + } else { + data.type = INVALID_FORMAT; + } + } else { + QString format = HbThemeServerUtils::formatFromPath(key.filename); + QT_TRY { + tempIconCacheItem.reset(HbIconCacheItemCreator::createCacheItem(key, + (HbIconLoader::IconLoaderOptions)options, + format, + false)); + cacheItem = tempIconCacheItem.data(); + if (cacheItem) { + if (cacheItem->rasterIconData.type != INVALID_FORMAT) { + data = cacheItem->rasterIconData; + } else if (cacheItem->vectorIconData.type != INVALID_FORMAT) { + data = cacheItem->vectorIconData; + } else if (cacheItem->blobIconData.type != INVALID_FORMAT) { + data = cacheItem->blobIconData; + } else { + data.type = INVALID_FORMAT; + } + if (data.type != INVALID_FORMAT) { + insertKeyIntoSessionList = iServer->insertIconCacheItem(key, cacheItem); + } + } + } QT_CATCH(const std::bad_alloc &) { + data.type = INVALID_FORMAT; + } + } + if (insertKeyIntoSessionList) { + //The session will only keep track of icons that were either successfully found or were + //successfully inserted in the cache. + sessionIconData.append(key); + } + + tempIconCacheItem.take(); + + QByteArray outputByteArray; + QDataStream outputDataStream(&outputByteArray, QIODevice::WriteOnly); + HbThemeServerRequest request; + request = EIconLookup; + outputDataStream << (int)request; + outputDataStream << (int)data.type; + + if (data.type == OTHER_SUPPORTED_FORMATS) { + outputDataStream << data.pixmapData.offset; + outputDataStream << data.pixmapData.width; + outputDataStream << data.pixmapData.height; + outputDataStream << data.pixmapData.defaultWidth; + outputDataStream << data.pixmapData.defaultHeight; + outputDataStream << (int)data.pixmapData.format; + } else if (/*data.type == SVG || */data.type == PIC) { + outputDataStream << data.picData.offset; + outputDataStream << data.picData.dataSize; + outputDataStream << data.picData.defaultWidth; + outputDataStream << data.picData.defaultHeight; + } else if (data.type == NVG) { + outputDataStream << data.nvgData.offset; + outputDataStream << data.nvgData.dataSize; + } else if (data.type == BLOB) { + outputDataStream << data.blobData.offset; + outputDataStream << data.blobData.dataSize; + } +#ifdef THEME_SERVER_TRACES + qDebug() << Q_FUNC_INFO << " offset= " << data.pixmapData.offset << " format= " << data.pixmapData.format; + testLabel->setPixmap(QPixmap::fromImage( + QImage( + HbMemoryUtils::getAddress(HbMemoryManager::SharedMemory, data.pixmapData.offset), + data.pixmapData.width, + data.pixmapData.height, + data.pixmapData.format))); +#endif + + return outputByteArray; +} + +/** + * HbThemeServerPrivate::doCleanup() + * + * This function releases shared memory occupied by css-resources whose reference count is zero, + * so that subsequent css-requests could be fulfilled by the server. Those css-files whose reference + * count are zero, are already appended to the list maintained by the css-cache. Since these resources + * are not being referred to by any application, they can be removed from the cache and corresponding + * shared memory can be freed up. + */ +void HbThemeServerPrivate::doCleanup() +{ + HbThemeServerUtils::cleanupUnusedCss(cssCache); +} + +/** + * HbThemeServerPrivate::sessionListCount() + * Gives the list count of Sessions. + */ +int HbThemeServerPrivate::sessionListCount() const +{ + return sessionList.count(); +} +