123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /**
- * Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- *
- * For the applicable distribution terms see the license.txt -file, included in
- * the distribution.
- */
- #include <iapclient.h>
- #include <QDebug>
- #include <QApplication>
- #include <QFile>
- #include <QDir>
- #include "purchasableitembase.h"
- #include "declarativepurchaselistmodel.h"
- #define TICKETFOLDERNAME "tickets"
- Q_DECLARE_METATYPE(IAPClient::ProductList) //to be able to transfer data this type with Qt::QueuedConnection
- Q_DECLARE_METATYPE(IAPClient::ProductDataList)
- // local function declaration
- bool isTheSameProduct(IAPClient::ProductDataHash& left, IAPClient::ProductData& right);
- PurchasableItemBase::PurchasableItemBase(DeclarativePurchaseListModel& model, QString& productID, QString& productUrl) :
- QObject(&model), //parent
- m_model(&model),
- m_isBusy(false),
- m_isKnown(false),
- m_unlocked_icon(NULL),
- m_buy_icon(NULL),
- m_notready_icon(NULL),
- m_productUrl(productUrl)
- {
- m_productMetadata.productId = productID;
- // connect IAP API's signals to app's slots
- IAPClient *client = &m_model->client();
- qRegisterMetaType<IAPClient::ProductDataHash>("IAPClient::ProductDataHash");
- connect(client, SIGNAL(productDataReceived( int, QString, IAPClient::ProductDataHash)),
- this, SLOT(productDataReceived(int, QString, IAPClient::ProductDataHash)), Qt::QueuedConnection);
- connect(client, SIGNAL(purchaseCompleted( int , QString, QString)),
- this, SLOT(purchaseCompleted( int , QString, QString)),Qt::QueuedConnection);
- connect(client, SIGNAL(purchaseFlowFinished(int)),
- this, SLOT(purchaseFlowFinished(int)), Qt::QueuedConnection);
- connect(client, SIGNAL(restorationCompleted (int , QString , QString)),
- this, SLOT(restorationCompleted (int , QString , QString)), Qt::QueuedConnection);
- //initialize data
- m_productMetadata.dataRequestResult = "Pending";
- m_productMetadata.drmProtection = IAPClient::NokiaDrm;
- fetchMetadata();
- }
- PurchasableItemBase::~PurchasableItemBase()
- {
- delete m_unlocked_icon;
- m_unlocked_icon = NULL;
- delete m_buy_icon;
- m_buy_icon = NULL;
- delete m_notready_icon;
- m_notready_icon = NULL;
- }
- QVariant PurchasableItemBase::metadata(int role) const
- {
- switch(role)
- {
- case ProductIdRole:
- return m_productMetadata.productId;
- case DataReqResultRole:
- return m_productMetadata.dataRequestResult;
- case TitleRole:
- return m_productMetadata.title;
- case ShortDescriptionRole:
- return m_productMetadata.shortDescription;
- case LongDescriptionRole:
- return m_productMetadata.longDescription;
- case PriceRole:
- return m_productMetadata.price;
- case DrmProtectionRole:
- return ((m_productMetadata.drmProtection == IAPClient::NokiaDrm) ? true : false);
- case IsMetadataKnown:
- return m_isKnown;
- case IsBusy:
- return m_isBusy;
- case IsActivated:
- return (isActivated());
- default:
- break;
- }
- return QVariant();
- }
- bool PurchasableItemBase::setMetadata(const QVariant & value, int role)
- {
- bool result = true;
- switch(role)
- {
- case ProductIdRole:
- m_productMetadata.productId = value.toString();
- break;
- case DataReqResultRole:
- m_productMetadata.dataRequestResult = value.toString();
- break;
- case TitleRole:
- m_productMetadata.title = value.toString();
- break;
- case ShortDescriptionRole:
- m_productMetadata.shortDescription = value.toString();
- break;
- case LongDescriptionRole:
- m_productMetadata.longDescription = value.toString();
- break;
- case PriceRole:
- m_productMetadata.price = value.toString();
- break;
- case DrmProtectionRole:
- m_productMetadata.drmProtection = (value.toBool()) ? IAPClient::NokiaDrm : IAPClient::OtherDrm;
- break;
- case IsMetadataKnown: //read-only properties
- case IsBusy:
- m_isBusy = value.toBool();
- break;
- case IsActivated:
- // cannot be unlocked by this call but can be locked
- if(value.toBool())
- result = false;
- else
- deactivate();
- break;
- default:
- result = false;
- break;
- }
- return result;
- }
- void PurchasableItemBase::deactivate()
- {
- delete m_unlocked_icon;
- m_unlocked_icon = NULL;
- }
- bool PurchasableItemBase::isMetaDataKnown() const
- {
- return m_isKnown;
- }
- bool PurchasableItemBase::isBusy()
- {
- return m_isBusy;
- }
- bool PurchasableItemBase::isActivated() const
- {
- return (m_unlocked_icon != NULL);
- }
- void PurchasableItemBase::fetchMetadata()
- {
- qDebug(__FUNCTION__);
- if(setBusy())
- {
- m_requestId = m_model->client().getProductData(m_productMetadata.productId);
- }
- }
- void PurchasableItemBase::purchase()
- {
- qDebug(__FUNCTION__);
- if(setBusy())
- {
- m_requestId = m_model->client().purchaseProduct(m_productMetadata.productId, IAPClient::NoForcedRestoration);
- }
- }
- void PurchasableItemBase::restore()
- {
- qDebug(__FUNCTION__);
- if(setBusy())
- {
- qDebug() << "restoreProduct : " << m_productMetadata.productId;
- m_requestId = m_model->client().restoreProduct(m_productMetadata.productId);
- }
- }
- void PurchasableItemBase::productDataReceived(int requestId, QString status,
- IAPClient::ProductDataHash productData)
- {
- if(requestId != m_requestId)
- return;
- qDebug(__FUNCTION__);
- m_model->beginModelUpdate();
- m_isBusy = false;
- m_isKnown = true;
- IAPClient::DrmType type = m_productMetadata.drmProtection;
- QString productId = m_productMetadata.productId;
- m_productMetadata.title = productData.value("info").toString();
- m_productMetadata.shortDescription = productData.value("shortdescription").toString();
- m_productMetadata.longDescription = productData.value("description").toString();
- m_productMetadata.price = productData.value("price").toString();
- m_productMetadata.dataRequestResult = productData.value("result").toString();
- m_productMetadata.drmProtection = type; //preserve DRM type
- m_productMetadata.productId = productId; //preserve Product ID
- if(isPurchased())
- setUnlocked(NULL);
- m_model->commitModelUpdate();
- }
- void PurchasableItemBase::purchaseCompleted(int requestId, QString status, QString purchaseTicket)
- {
- if(requestId != m_requestId)
- return;
- qDebug(__FUNCTION__);
- m_model->beginModelUpdate();
- m_isBusy = false;
- if(status.compare("OK", Qt::CaseSensitive) == 0)
- {
- setUnlocked(&purchaseTicket);
- }
- m_model->commitModelUpdate();
- }
- void PurchasableItemBase::purchaseFlowFinished(int requestId)
- {
- if(requestId != m_requestId)
- return;
- qDebug(__FUNCTION__);
- m_isBusy = false;
- }
- void PurchasableItemBase::restorationCompleted(int requestId, QString status, QString purchaseTicket)
- {
- if(requestId != m_requestId)
- return;
- qDebug(__FUNCTION__);
- m_model->beginModelUpdate();
- m_isBusy = false;
- if(status.compare("OK", Qt::CaseSensitive) == 0)
- {
- setUnlocked(&purchaseTicket);
- }
- m_model->commitModelUpdate();
- }
- void PurchasableItemBase::restorationFlowFinished(int requestId)
- {
- if(requestId != m_requestId)
- return;
- qDebug(__FUNCTION__);
- m_isBusy = false;
- }
- QImage& PurchasableItemBase::stateIcon() const
- {
- if(m_unlocked_icon)
- return *m_unlocked_icon;
- else if(m_isKnown)
- return *m_buy_icon;
- else
- return *m_notready_icon;
- }
- bool PurchasableItemBase::setBusy()
- {
- if(isActivated())
- return false; // already unlocked, no remote operation possible
-
- if(m_isBusy)
- {
- qDebug() << "item is busy. you can set only one request at time on the item";
- return false;
- }
- m_model->beginModelUpdate();
- m_isBusy = true;
- m_model->commitModelUpdate();
- return true;
- }
- void PurchasableItemBase::saveTicket(QString* purchaseTicket)
- {
- if(!purchaseTicket)
- return;
- QString privatedir(getTicketDir());
- if(!QDir(privatedir).exists())
- QDir().mkdir(privatedir);
- QFile file(getTicketUri());
- if(file.open(QIODevice::WriteOnly))
- {
- QDataStream out(&file);
- out << *purchaseTicket;
- file.close();
- }
- else
- {
- qDebug() << "PurchasableItemBase::testModeSaveTicket >>> Cannot open file for writing: ";
- }
- }
- bool PurchasableItemBase::readTicket()
- {
- return (QFile(getTicketUri()).exists());
- }
- QString PurchasableItemBase::getTicketUri()
- {
- QString fname(QApplication::applicationDirPath());
- fname.append("/");
- fname.append(TICKETFOLDERNAME);
- fname.append("/");
- fname.append(m_productMetadata.productId);
- fname.append(".ticket");
- return fname;
- }
- QString PurchasableItemBase::getTicketDir()
- {
- QString fname(QApplication::applicationDirPath());
- fname.append("/");
- fname.append(TICKETFOLDERNAME);
- return fname;
- }
- bool PurchasableItemBase::isIncluded(IAPClient::ProductDataList& list)
- {
- foreach(IAPClient::ProductDataHash item, list)
- {
- if(isTheSameProduct(item, m_productMetadata))
- return true;
- }
- return false;
- }
- bool isTheSameProduct(IAPClient::ProductDataHash& left, IAPClient::ProductData& right)
- {
- return (left.value("id").toString().compare(right.productId) == 0);
- }
|