userguide/src/HelpDataProvider.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 18 Aug 2010 09:39:48 +0300
changeset 39 30223e2ae041
parent 34 4533d75b8d4e
permissions -rw-r--r--
Revision: 201031 Kit: 201033

/*
* 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: 
*
*/

#include <QStandardItemModel>
#include <QXmlQuery>
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>
#include <QDir>

#include "HelpUtils.h"
#include "HelpCommon.h"
#include "HelpProxyModel.h"
#include "HelpStandardItem.h"

#include "HelpDataProvider.h"


HelpDataProvider::HelpDataProvider()
{
	mHelpModel = new QStandardItemModel();
	mKeywordModel = new QStandardItemModel();
	mSearhResultModel = new HelpProxyModel();
	mSearhResultModel->setSourceModel(mKeywordModel);
	mAppItem = NULL;
}

HelpDataProvider::~HelpDataProvider()
{
	delete mHelpModel;
	delete mSearhResultModel;
	delete mKeywordModel;
}


///////////////////////////////////////////////////////////////////////////////////////

HelpDataProvider* gHelpDataProviderInstance = NULL;

HelpDataProvider* HelpDataProvider::instance()
{
    if(!gHelpDataProviderInstance)
    {
        gHelpDataProviderInstance = new HelpDataProvider();
    }

    return gHelpDataProviderInstance;
}

void HelpDataProvider::destroyInstance()
{
    delete gHelpDataProviderInstance;
    gHelpDataProviderInstance = NULL;
}


///////////////////////////////////////////////////////////////////////////////////////

QAbstractItemModel* HelpDataProvider::getCategoryData()
{
    return mHelpModel;
}

QAbstractItemModel* HelpDataProvider::getSearchData(const QString& key)
{
	if(key == mLastSrhKey)
	{
		return mSearhResultModel;
	}

	mLastSrhKey = key;
    mSearhResultModel->setFilterRegExp(key);

	
    return mSearhResultModel;
}

void HelpDataProvider::setHelpContentUrl(const QString& uid, const QString& href)
{
    QUrl url = QUrl::fromLocalFile(uid+BACKSLASH+href);
    mHelpContentRoot = url.toString();
}

void HelpDataProvider::getHelpContentData(QString& content, QString& url)
{
    // url
    if(url.isEmpty())
    {
        url = mHelpContentRoot;
    }
    url.remove(URL_HEADER_LOCAL);

    // uid
    QString uid = url.section(BACKSLASH, 0, -3);
    uid.append(BACKSLASH + url.section(BACKSLASH, -2,-2));

    // href
    QString href = url.section(BACKSLASH, -1,-1);
    int anchorPos = href.indexOf(HASHMARK);
    if(anchorPos != -1)
    {
        href = href.section(HASHMARK, 0, 0);
    }

    QString path(uid);
    path.append(BACKSLASH);
    path.append(CONTENTSZIP);
    HelpUtils::loadHtmlFromZipFile(path , href, content);
}


///////////////////////////////////////////////////////////////////////////////////////

void HelpDataProvider::createHelpCategory()
{
	constructCategory();

	mHelpModel->setSortRole(Qt::DisplayRole);

	constructCategory2((HelpStandardItem*)mHelpModel->invisibleRootItem());

	if(mAppItem)
	{
		mHelpModel->appendRow(mAppItem);
		mAppItem->sortChildren(0, HelpUtils::sortOrder());
		constructCategory2(mAppItem);
	}	

	mKeywordModel->sort(0, HelpUtils::sortOrder());
}

void HelpDataProvider::constructCategory()
{
	QFileInfoList driveList = QDir::drives();
	QDir dir;
	QString lang = HelpUtils::UILocaleFromQtToSymbian();

	QString path(HelpUtils::rootPath());
	path.append(XHTMLPATH);
	path.append(lang);

	QStringList uidList;
	QStringList titleList;
	parseCategoryIndexXml(path, uidList, titleList);

	//scan other root path and construct 3rd party help
	foreach(QFileInfo fi, driveList)
	{
		path.clear();
		path.append(fi.absolutePath());
		path.append(XHTMLPATH);
		path.append(lang);
		dir.setPath(path);
		if(dir.exists())
		{
			if(QString::compare(fi.absolutePath(), HelpUtils::rootPath(), Qt::CaseInsensitive) == 0)
			{
				continue;
			}
			constructAppCategory(path, uidList);
		}
	}

	constructBuiltInCategory(path, uidList, titleList);

	mHelpModel->setSortRole(PriorityRole);
	mHelpModel->sort(0, HelpUtils::sortOrder());
}

void HelpDataProvider::constructBuiltInCategory(const QString& path, const QStringList& uidList, const QStringList& titleList)
{
	if(uidList.count() != titleList.count())
	{
		//ToDo
		return;
	}

	for(int i = 0; i < uidList.count(); i++)
	{
		if(mUpdateUidList.contains(uidList[i]))
		{
			continue;
		}

		QString uid(path);
		uid.append(BACKSLASH);
		uid.append(uidList[i]);

		constructBuiltInCategoryItem(uid, titleList[i]);
	}
}

void HelpDataProvider::constructAppCategory(const QString& path, QStringList& uidList)
{
	QDir dir(path);	
	if(!dir.exists())
	{
		return;
	}

	QStringList uidDirList = dir.entryList();
	QString pathUid;
	foreach(QString uid, uidDirList)
	{
		pathUid.clear();
		pathUid.append(path);
		pathUid.append(BACKSLASH);
		pathUid.append(uid);

		QString titleStr;
		parseAppMetaxml(pathUid, titleStr);
		if(titleStr.isEmpty())
		{
			continue;
		}

		if(uidList.contains(uid) || mUpdateUidList.contains(uid))
		{
			mUpdateUidList.append(uid);
			constructBuiltInCategoryItem(pathUid, titleStr);
			continue;
		}

		HelpStandardItem* item = NULL;
		item = new HelpStandardItem(titleStr);

		if(!item)
		{
			//no memory
			return;
		}

		item->setData(pathUid, UidRole);

		if(!mAppItem)
		{
			mAppItem = new HelpStandardItem(qtTrId(TXT_APPLICATIONS));
			if(!mAppItem)
			{
				//no memory
				return;
			}
			mAppItem->setData(APPPRIORITY, PriorityRole);
		}
		mAppItem->appendRow(item);
	}
}

void HelpDataProvider::constructBuiltInCategoryItem(const QString& uid, const QString& title)
{
	int priority;
	parseBuiltInMetaxml(uid, priority);
	
	HelpStandardItem* item = NULL;
	item = new HelpStandardItem(title);

	if(!item)
	{
		//no memory
		return;
	}
	item->setData(uid, UidRole);
	item->setData(priority, PriorityRole);
	mHelpModel->appendRow(item);
}

void HelpDataProvider::constructCategory2(HelpStandardItem* itemParent)
{
	int count = itemParent->rowCount();
	for(int i =0; i < count; i++)
	{
		HelpStandardItem* item = (HelpStandardItem*)itemParent->child(i);
		constructCategory2Item(item);
	}
}

void HelpDataProvider::constructCategory2Item(HelpStandardItem* itemParent)
{
	QStringList hrefList;
	QStringList titleList;

	QString uid = itemParent->data(UidRole).toString();
	parseCategory2IndexXml(uid, hrefList, titleList);

	if(hrefList.count() == 0 || hrefList.count() != titleList.count())
	{
		return;
	}

	for(int i = 0; i < hrefList.count(); i++)
	{
		HelpStandardItem* item = NULL;
		item = new HelpStandardItem(titleList[i]);
		if(!item)
		{
			//no memory
			return;
		}
		item->setData(hrefList[i], HrefRole);
		item->setData(uid, UidRole);
		itemParent->appendRow(item);
		constructKeywordModel(titleList[i], uid, hrefList[i]);
	}

	itemParent->sortChildren(0, HelpUtils::sortOrder());
}

void HelpDataProvider::constructKeywordModel(const QString& title, const QString& uid, const QString& href)
{
	HelpStandardItem* item = NULL;
	item = new HelpStandardItem(title);
	if(!item)
	{
		//no memory
		return;
	}
	item->setData(uid, UidRole);
	item->setData(href, HrefRole);
	mKeywordModel->appendRow(item);
}

void HelpDataProvider::parseCategoryIndexXml(const QString& path, QStringList& uidList, QStringList& titleList)
{
	QString pathIndex(path);
	pathIndex.append(BACKSLASH);
	pathIndex.append(INDEXXML);

	QFile file(pathIndex);
	if (!file.open(QIODevice::ReadOnly)) {
		return;
	}

	//parse index xml to a stringlist, each string include id and navtitle and seperate by "specilchar"
	QXmlQuery query;
	query.bindVariable("inputdoc", &file);

	query.setQuery("doc($inputdoc)/collections/collection/xs:string(@id)");
	if(!query.isValid())
	{
		return;
	}
	if(!query.evaluateTo(&uidList))
	{
		return;
	}

	query.setQuery("doc($inputdoc)/collections/collection/xs:string(@navtitle)");
	if(!query.isValid())
	{
		return;
	}
	if(!query.evaluateTo(&titleList))
	{
		return;
	}

	QStringList featureIdLst;

	query.setQuery("doc($inputdoc)/collections/collection/number(@FeatureId)");
	if(!query.isValid())
	{
		return;
	}
	if(!query.evaluateTo(&featureIdLst))
	{
		return;
	}

	if(featureIdLst.count() != uidList.count())
	{
		return;
	}

	for(int i = featureIdLst.count()  - 1; i >= 0; i--)
	{
		int featureID = featureIdLst.at(i).toInt();
		if(!HelpUtils::suppportFeatureID(featureID))
		{
			uidList.removeAt(i);
			titleList.removeAt(i);
		}
	}
}

void HelpDataProvider::parseCategory2IndexXml(const QString& path, QStringList& hrefList, QStringList& titleList)
{
	QString pathIndex(path);
	pathIndex.append(BACKSLASH);
	pathIndex.append(INDEXXML);

	QFile file(pathIndex);
	if (!file.open(QIODevice::ReadOnly)) {
		return;
	}

	//parse index xml to a stringlist, each string include href and navtitle and seperate by "specilchar"
	QXmlQuery query;
	query.bindVariable("inputdoc", &file);

	query.setQuery("doc($inputdoc)/topics/topicref/xs:string(@href)");	
	if(!query.isValid())
	{
		return;
	}
	if(!query.evaluateTo(&hrefList))
	{
		return;
	}	

	query.setQuery("doc($inputdoc)/topics/topicref/xs:string(@navtitle)");
	if(!query.isValid())
	{
		return;
	}
	if(!query.evaluateTo(&titleList))
	{
		return;
	}

	QStringList featureIdLst;

	query.setQuery("doc($inputdoc)/topics/topicref/number(@FeatureId)");
	if(!query.isValid())
	{
		return;
	}
	if(!query.evaluateTo(&featureIdLst))
	{
		return;
	}

	if(featureIdLst.count() != hrefList.count())
	{
		return;
	}

	for(int i = featureIdLst.count()  - 1; i >= 0; i--)
	{
		int featureID = featureIdLst.at(i).toInt();
		if(!HelpUtils::suppportFeatureID(featureID))
		{
			hrefList.removeAt(i);
			titleList.removeAt(i);
		}
	}
}

void HelpDataProvider::parseBuiltInMetaxml(const QString& path, int& priority)
{
	QString pathMetaxml(path);
	pathMetaxml.append(BACKSLASH);
	pathMetaxml.append(METAXML);

	priority = -1;

	QFile file(pathMetaxml);
	if (!file.open(QIODevice::ReadOnly))
	{
		return;
	}

	QXmlQuery query;
	QString str;
	query.bindVariable("inputdoc", &file);

	query.setQuery("doc($inputdoc)/meta/number(priority)");	
	if(query.isValid() && query.evaluateTo(&str))
	{
		priority = str.toInt();
	}
}

void HelpDataProvider::parseAppMetaxml(const QString& path, QString& title)
{
	QString pathMetaxml(path);
	pathMetaxml.append(BACKSLASH);
	pathMetaxml.append(METAXML);
	QFile file(pathMetaxml);
	if (!file.open(QIODevice::ReadOnly)) {
		return;
	}

	//parse meta xml, get the title string
	QXmlQuery query;
	query.bindVariable("inputdoc", &file);
	query.setQuery("doc($inputdoc)/meta/string(title)");
	if(!query.isValid())
	{
		return;
	}

	if(!query.evaluateTo(&title))
	{
		return;
	}
}