123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- /*
- * Copyright (c) 2011 Nokia Corporation.
- */
- #include "levelcontroller.h"
- #include "levelmodel.h"
- #include "level.h"
- #include <QFile>
- #include <QTextStream>
- #include <QStringList>
- #include <QMessageBox>
- LevelController::LevelController(Level *level,QObject *parent) :
- QObject(parent)
- {
- /***********************************************************************************************
- *Create a level model and a IAPClient object. *
- ***********************************************************************************************/
- m_Model = new LevelModel(this);
- #if defined(IAP_ENABLED)
- m_IAPClient = new IAPClient(this);
- #endif
- /***********************************************************************************************
- *Set the level object. *
- ***********************************************************************************************/
- m_level = level;
- /***********************************************************************************************
- *Register metatype for IAPClient::ProductData, to be able to use QueuedConnection. *
- ***********************************************************************************************/
- #if defined(IAP_ENABLED)
- qRegisterMetaType<IAPClient::ProductData>("IAPClient::ProductData");
- #endif
- /***********************************************************************************************
- *Make connections. *
- ***********************************************************************************************/
- #if defined(IAP_ENABLED)
- connect(m_IAPClient,SIGNAL(productDataReceived(int,QString,IAPClient::ProductData)),
- this,SLOT(productDataReceved(int,QString,IAPClient::ProductData)),Qt::QueuedConnection);
- connect(m_IAPClient,SIGNAL(restorableProductsReceived(int,QString,IAPClient::ProductList)),
- this,SLOT(restorableProductsReceived(int,QString,IAPClient::ProductList)));
- connect(m_IAPClient,SIGNAL(userAndDeviceDataReceived(int,QString,QString,QString,QString,QString,QString)),
- this,SLOT(userAndDeviceDataReceived(int,QString,QString,QString,QString,QString,QString)));
- connect(m_IAPClient,SIGNAL(purchaseCompleted(int,QString,QString)),
- this,SLOT(purchaseCompleted(int,QString,QString)));
- connect(m_IAPClient,SIGNAL(purchaseFlowFinished(int)),
- this,SLOT(purchaseFlowFinished(int)));
- connect(m_IAPClient,SIGNAL(restorationCompleted(int,QString,QString)),
- this,SLOT(restorationCompleted(int,QString,QString)));
- connect(m_IAPClient,SIGNAL(restorationFlowFinished(int)),
- this,SLOT(restorationFlowFinished(int)));
- #endif
- /**********************************************************************************************/
- /***********************************************************************************************
- *Load items and set the default theme. *
- ***********************************************************************************************/
- loadItems();
- face = ":/images/face-smile.png";
- }
- void LevelController::load(int index)
- {
- /***********************************************************************************************
- *Create a ModelIndex for the given index. *
- ***********************************************************************************************/
- QModelIndex i = m_Model->index(index);
- if(i.isValid()){
- /*******************************************************************************************
- *If index is valid, extract levelId and type. *
- *******************************************************************************************/
- QString levelId = m_Model->data(i,LevelModel::LevelIdRole).toString();
- QString levelType = m_Model->data(i,LevelModel::LevelType).toString();
- if(levelId != LEVEL_INVALID){
- /***************************************************************************************
- *If type == Level, trigger level loading. *
- ***************************************************************************************/
- if(levelType == "Level" &&
- m_level->load(QString("%1.xml").arg(levelId)))
- emit levelReload();
- /***************************************************************************************
- *If type == Theme, extract theme name and set new theme. *
- ***************************************************************************************/
- else if(levelType == "Theme"){
- face = QString(":/images/face-%1.png")
- .arg(m_Model->data(i,LevelModel::LevelNameRole).toString());
- emit faceChanged();
- }
- }
- }
- }
- void LevelController::buy(int index)
- {
- /***********************************************************************************************
- *Set initial id to LEVEL_INVALID. *
- ***********************************************************************************************/
- QString itemId = LEVEL_INVALID;
- /***********************************************************************************************
- *Create a ModelIndex for the given index. *
- ***********************************************************************************************/
- QModelIndex i = m_Model->index(index);
- if(i.isValid())
- /*******************************************************************************************
- *If index is valid, extract levelId. *
- *******************************************************************************************/
- itemId = m_Model->data(i,LevelModel::LevelIdRole).toString();
- if(itemId != LEVEL_INVALID){
- /*******************************************************************************************
- *If id valid, call the IAP purchase method. *
- *******************************************************************************************/
- #if defined(IAP_ENABLED)
- int requestId = m_IAPClient->purchaseProduct(itemId,IAPClient::ForcedAutomaticRestoration);
- if(requestId > 0){
- /***************************************************************************************
- *If requestId valid, extract item name and add a new entry to the request queue. *
- ***************************************************************************************/
- QString name = m_Model->data(i,LevelModel::LevelNameRole).toString();
- levelRequests.insert(requestId,QPair<QString,QString>(itemId,name));
- }
- #endif
- }
- }
- /***************************************************************************************************
- *Simple access methods. *
- ***************************************************************************************************/
- LevelModel* LevelController::getLevelModel() const
- {
- return m_Model;
- }
- QString LevelController::getFace() const
- {
- return face;
- }
- /**************************************************************************************************/
- #if defined(IAP_ENABLED)
- void LevelController::productDataReceved(int requestId,QString status,IAPClient::ProductData data)
- {
- /***********************************************************************************************
- *Check response status. *
- ***********************************************************************************************/
- if(status.compare("OK",Qt::CaseInsensitive) == 0){
- /*******************************************************************************************
- *Set initial id,name and type to LEVEL_INVALID and unlocked false. *
- *******************************************************************************************/
- QString id = LEVEL_INVALID;
- QString name = LEVEL_INVALID;
- QString type = LEVEL_INVALID;
- bool unlocked = false;
- /*******************************************************************************************
- *Check the request type by looking in the right queue. *
- *******************************************************************************************/
- if(levelRequests.contains(requestId)){
- /***************************************************************************************
- *If requested item is a Level, extract id and name, set type to Level. *
- *Check if the file "itemId.xml" exists, if positive the level has been unlocked. *
- ***************************************************************************************/
- QPair<QString,QString> idName = levelRequests.take(requestId);
- id = idName.first;
- name = idName.second;
- type = "Level";
- unlocked = QFile::exists(QString("%1.xml").arg(id));
- }else if(themeRequests.contains(requestId)){
- /***************************************************************************************
- *If requested item is a Theme, extract id and name, set type to Theme. *
- *Check if the file "itemId" exists, if positive the theme has been unlocked. *
- ***************************************************************************************/
- QPair<QString,QString> idName = themeRequests.take(requestId);
- id = idName.first;
- name = idName.second;
- type = "Theme";
- unlocked = QFile::exists(QString("%1").arg(id));
- }
- if(type != LEVEL_INVALID){
- /***************************************************************************************
- *If item type set, create and populate a new LevelData struct. *
- ***************************************************************************************/
- LevelData levelData;
- levelData.id = id;
- levelData.data = data;
- levelData.name = name;
- levelData.type = type;
- levelData.unlocked = unlocked;
- /***************************************************************************************
- *Add item to model. *
- ***************************************************************************************/
- m_Model->setLevelData(levelData);
- }
- /*******************************************************************************************
- *Call request item data, to request next items data retrieval. *
- *******************************************************************************************/
- requestItemData();
- }
- }
- void LevelController::restorableProductsReceived(int requestId,QString status,
- IAPClient::ProductList data)
- {
- }
- void LevelController::userAndDeviceDataReceived(int requestId,QString account,QString imei,QString imsi,
- QString country,QString language,QString deviceModel)
- {
- }
- void LevelController::purchaseCompleted(int requestId,QString status,QString purchaseTicked)
- {
- /***********************************************************************************************
- *Check if the request queue contains the requestId. *
- ***********************************************************************************************/
- if(levelRequests.contains(requestId)){
- /*******************************************************************************************
- *Check response status. *
- *******************************************************************************************/
- if(status.compare("OK",Qt::CaseInsensitive) == 0){
- /***************************************************************************************
- *If status == OK, unlock purchase item. *
- ***************************************************************************************/
- unlock(levelRequests.value(requestId).first,purchaseTicked);
- }else if(status.compare("RestorableProduct",Qt::CaseInsensitive) == 0){
- /***************************************************************************************
- *If status == RestorableProduct, start the product restoration flow. *
- ***************************************************************************************/
- int resotreRequestId = m_IAPClient->restoreProduct(levelRequests.value(requestId).first);
- if(resotreRequestId > 0)
- levelRequests.insert(resotreRequestId,levelRequests.take(requestId));
- }
- }
- }
- void LevelController::purchaseFlowFinished(int requestId)
- {
- /***********************************************************************************************
- *Remove the request form the queue. Emit the hack signal to hide the software keys. *
- ***********************************************************************************************/
- levelRequests.remove(requestId);
- emit hack();
- }
- void LevelController::restorationCompleted(int requestId,QString status,QString purchaseTicked)
- {
- /***********************************************************************************************
- *Check if the request queue contains the requestId. *
- ***********************************************************************************************/
- if(levelRequests.contains(requestId)){
- /*******************************************************************************************
- *Check response status. *
- *******************************************************************************************/
- if(status.compare("OK",Qt::CaseInsensitive) == 0)
- /***************************************************************************************
- *If status == OK, unlock purchase item. *
- ***************************************************************************************/
- unlock(levelRequests.value(requestId).first,purchaseTicked);
- }
- }
- void LevelController::restorationFlowFinished(int requestId)
- {
- /***********************************************************************************************
- *Remove the request form the queue. Emit the hack signal to hide the software keys. *
- ***********************************************************************************************/
- levelRequests.remove(requestId);
- emit hack();
- }
- #endif
- void LevelController::loadItems()
- {
- /***********************************************************************************************
- *Check if the file "Item.data" exists. *
- ***********************************************************************************************/
- if(QFile::exists("Items.data")){
- /*******************************************************************************************
- *Open the file in read-only mode. *
- *******************************************************************************************/
- QFile dataFile("Items.data");
- if(dataFile.open(QIODevice::ReadOnly)){
- /***************************************************************************************
- *Create a QTextStream to read the files contents. *
- ***************************************************************************************/
- QTextStream readStream(&dataFile);
- while(!readStream.atEnd())
- {
- /***********************************************************************************
- *Read line, append read lines to the itemLines list ignoring comment lines. *
- ***********************************************************************************/
- QString line = readStream.readLine();
- if(line.startsWith("#")) continue;
- itemLines.append(line);
- }
- /***************************************************************************************
- *Call request item data, to request first items data retrieval. *
- ***************************************************************************************/
- requestItemData();
- }
- }
- }
- void LevelController::requestItemData()
- {
- /***********************************************************************************************
- *Check if there are any pending lines. *
- ***********************************************************************************************/
- if(itemLines.count() > 0)
- {
- /*******************************************************************************************
- *Split the line using ';'. *
- *******************************************************************************************/
- QStringList lineContent = itemLines.takeFirst().split(";");
- /*******************************************************************************************
- *Check if the line contains exactly 3 elements. *
- *******************************************************************************************/
- if(lineContent.count() == 3){
- /***************************************************************************************
- *Check item type and add the request to the appropriate queue. *
- ***************************************************************************************/
- #if defined(IAP_ENABLED)
- if(lineContent.at(1).compare("LEVEL",Qt::CaseInsensitive) == 0){
- QString name = lineContent.at(2);
- int requestId = m_IAPClient->getProductData(lineContent.at(0));
- levelRequests.insert(requestId,QPair<QString,QString>(lineContent.at(0),name));
- }else if(lineContent.at(1).compare("THEME",Qt::CaseInsensitive) == 0){
- QString name = lineContent.at(2);
- int requestId = m_IAPClient->getProductData(lineContent.at(0));
- themeRequests.insert(requestId,QPair<QString,QString>(lineContent.at(0),name));
- }
- #endif
- }
- }
- }
- void LevelController::unlock(QString itemId,QString purchaseTicket)
- {
- /***********************************************************************************************
- *The unlocking process implemented here is for presentation purposes only. *
- *A truly correct unlocking process needs to involve purchaseTicket validation via the *
- *Ticket Verification API and downloading the content form a dedicated server. *
- ***********************************************************************************************/
- Q_UNUSED(purchaseTicket)
- /***********************************************************************************************
- *Extract LevelData identified by itemId from the model. *
- ***********************************************************************************************/
- LevelData level = m_Model->getById(itemId);
- if(level.id != LEVEL_INVALID){
- /*******************************************************************************************
- *If level is valid, set unlocked to true. *
- *******************************************************************************************/
- level.unlocked = true;
- /*******************************************************************************************
- *Check item type. *
- *******************************************************************************************/
- if(level.type == "Level"){
- /***************************************************************************************
- *Create level file. *
- ***************************************************************************************/
- QFile source(QString(":/levels/%1.xml").arg(level.name));
- source.open(QIODevice::ReadOnly);
- QFile levelFile(QString("%1.xml").arg(itemId));
- levelFile.open(QIODevice::WriteOnly|QIODevice::Truncate);
- QTextStream stream(&levelFile);
- stream << source.readAll();
- }else if(level.type == "Theme"){
- /***************************************************************************************
- *Create theme file. *
- ***************************************************************************************/
- QFile levelFile(QString("%1").arg(itemId));
- levelFile.open(QIODevice::WriteOnly|QIODevice::Truncate);
- QTextStream stream(&levelFile);
- stream << level.name;
- }
- /*******************************************************************************************
- *Overwrite model item data *
- *******************************************************************************************/
- m_Model->setLevelData(level);
- }
- }
|