Commit b50eaa65 authored by kh's avatar kh
Browse files

Remove left over files.

Reviewed-by: dt
parent 73289b95
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "contentstoolwindow.h"
#include "helpengine.h"
#include <QtCore/QDebug>
#include <QtCore/QStack>
#include <QtGui/QFocusEvent>
#include <QtGui/QKeyEvent>
using namespace Help::Internal;
ContentsToolWidget::ContentsToolWidget()
{
wasInitialized = false;
setRootIsDecorated(true);
setItemHidden(headerItem(), true);
setUniformRowHeights(true);
setColumnCount(1);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setWindowTitle(tr("Contents"));
setWindowIcon(QIcon(":/help/images/book.png"));
}
void ContentsToolWidget::focusInEvent(QFocusEvent *e)
{
if (wasInitialized) {
if (e && e->reason() != Qt::MouseFocusReason
&& !currentItem() && topLevelItemCount())
setCurrentItem(topLevelItem(0));
return;
}
wasInitialized = true;
setCursor(QCursor(Qt::WaitCursor));
emit buildRequested();
}
void ContentsToolWidget::showEvent(QShowEvent *)
{
if (wasInitialized)
return;
wasInitialized = true;
setCursor(QCursor(Qt::WaitCursor));
emit buildRequested();
}
void ContentsToolWidget::keyPressEvent(QKeyEvent *e)
{
if (e && e->key() == Qt::Key_Escape) {
emit escapePressed();
e->accept();
return;
}
QTreeWidget::keyPressEvent(e);
}
enum
{
LinkRole = Qt::UserRole + 1000
};
ContentsToolWindow::ContentsToolWindow(const QList<int> &context, HelpEngine *help)
{
m_widget = new ContentsToolWidget;
helpEngine = help;
connect(helpEngine, SIGNAL(contentsInitialized()), this, SLOT(contentsDone()));
connect(m_widget, SIGNAL(buildRequested()), helpEngine, SLOT(buildContents()));
m_context = context;
m_context << 0;
connect(m_widget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(indexRequested()));
connect(m_widget, SIGNAL(escapePressed()), this, SIGNAL(escapePressed()));
}
ContentsToolWindow::~ContentsToolWindow()
{
delete m_widget;
}
const QList<int> &ContentsToolWindow::context() const
{
return m_context;
}
QWidget *ContentsToolWindow::widget()
{
return m_widget;
}
void ContentsToolWindow::contentsDone()
{
m_widget->setCursor(QCursor(Qt::WaitCursor));
QList<QPair<QString, ContentList> > contentList = helpEngine->contents();
for (QList<QPair<QString, ContentList> >::Iterator it = contentList.begin(); it != contentList.end(); ++it) {
QTreeWidgetItem *newEntry;
QTreeWidgetItem *contentEntry;
QStack<QTreeWidgetItem*> stack;
stack.clear();
int depth = 0;
bool root = false;
QTreeWidgetItem *lastItem[64];
for (int j = 0; j < 64; ++j)
lastItem[j] = 0;
ContentList lst = (*it).second;
for (ContentList::ConstIterator it = lst.begin(); it != lst.end(); ++it) {
ContentItem item = *it;
if (item.depth == 0) {
newEntry = new QTreeWidgetItem(m_widget, 0);
newEntry->setIcon(0, QIcon(QString::fromUtf8(":/help/images/book.png")));
newEntry->setText(0, item.title);
newEntry->setData(0, LinkRole, item.reference);
stack.push(newEntry);
depth = 1;
root = true;
} else {
if (item.depth > depth && root) {
depth = item.depth;
stack.push(contentEntry);
}
if (item.depth == depth) {
contentEntry = new QTreeWidgetItem(stack.top(), lastItem[ depth ]);
lastItem[ depth ] = contentEntry;
contentEntry->setText(0, item.title);
contentEntry->setData(0, LinkRole, item.reference);
}
else if (item.depth < depth) {
stack.pop();
depth--;
item = *(--it);
}
}
}
}
m_widget->setCursor(QCursor(Qt::ArrowCursor));
}
void ContentsToolWindow::indexRequested()
{
QTreeWidgetItem *itm = m_widget->currentItem();
if (!itm)
return;
emit showLinkRequested(itm->data(0, LinkRole).toString(), false);
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#ifndef CONTENTSTOOLWINDOW_H
#define CONTENTSTOOLWINDOW_H
#include <coreplugin/iview.h>
#include <QtGui/QTreeWidget>
namespace Help {
namespace Internal {
class HelpEngine;
class ContentsToolWindow;
class ContentsToolWidget : public QTreeWidget
{
Q_OBJECT
public:
ContentsToolWidget();
signals:
void buildRequested();
void escapePressed();
private:
friend class ContentsToolWindow;
void showEvent(QShowEvent *e);
void focusInEvent(QFocusEvent *e);
void keyPressEvent(QKeyEvent *e);
bool wasInitialized;
};
class ContentsToolWindow : public Core::IView
{
Q_OBJECT
public:
ContentsToolWindow(const QList<int> &context, HelpEngine *help);
~ContentsToolWindow();
const QList<int> &context() const;
QWidget *widget();
QList<QWidget*> dockToolBarWidgets() const { return QList<QWidget*>(); }
const char *uniqueViewName() const { return "Help.ContentsToolWindow"; }
const char *globalMenuGroup() const { return "Help.Group"; }
inline QKeySequence defaultShortcut() const { return QKeySequence(); }
Qt::DockWidgetArea defaultArea() const { return Qt::RightDockWidgetArea; }
IView::ViewPosition defaultPosition() const { return IView::First; }
signals:
void showLinkRequested(const QString &link, bool newWindow);
void escapePressed();
private slots:
void contentsDone();
void indexRequested();
private:
HelpEngine *helpEngine;
QList<int> m_context;
ContentsToolWidget *m_widget;
};
} // namespace Internal
} // namespace Help
#endif // CONTENTSTOOLWINDOW_H
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "helpengine.h"
#include "config.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QDateTime>
#include <QtCore/QCoreApplication>
using namespace Help::Internal;
static bool verifyDirectory(const QString &str)
{
QFileInfo dirInfo(str);
if (!dirInfo.exists())
return QDir().mkdir(str);
if (!dirInfo.isDir()) {
qWarning("'%s' exists but is not a directory", str.toLatin1().constData());
return false;
}
return true;
}
struct IndexKeyword
{
IndexKeyword(const QString &kw, const QString &l)
: keyword(kw), link(l) {}
IndexKeyword() : keyword(QString()), link(QString()) {}
bool operator<(const IndexKeyword &ik) const {
return keyword.toLower() < ik.keyword.toLower();
}
bool operator<=(const IndexKeyword &ik) const {
return keyword.toLower() <= ik.keyword.toLower();
}
bool operator>(const IndexKeyword &ik) const {
return keyword.toLower() > ik.keyword.toLower();
}
Q_DUMMY_COMPARISON_OPERATOR(IndexKeyword)
QString keyword;
QString link;
};
QDataStream &operator>>(QDataStream &s, IndexKeyword &ik)
{
s >> ik.keyword;
s >> ik.link;
return s;
}
QDataStream &operator<<(QDataStream &s, const IndexKeyword &ik)
{
s << ik.keyword;
s << ik.link;
return s;
}
/**
* Compare in a human-preferred alphanumeric way,
* e.g. 'Qt tutorial 2' will be less than 'Qt tutorial 11'.
*/
bool caseInsensitiveLessThan(const QString &as, const QString &bs)
{
const QChar *a = as.unicode();
const QChar *b = bs.unicode();
int result = 0;
while (result == 0)
{
ushort aa = a->unicode();
ushort bb = b->unicode();
if (aa == 0 || bb == 0) {
result = aa - bb;
break;
}
else if (a->isDigit() && b->isDigit())
{
const QChar *a_begin = a;
const QChar *b_begin = b;
bool loop = true;
do {
if (a->isDigit()) ++a;
else if (b->isDigit()) ++b;
else loop = false;
} while (loop);
// optimization: comparing the length of the two numbers is more efficient than constructing two qstrings.
result = (a - a_begin) - (b - b_begin);
if (result == 0) {
QString astr(a_begin, a - a_begin);
QString bstr(b_begin, b - b_begin);
long la = astr.toLong();
long lb = bstr.toLong();
result = la - lb;
}
} else {
aa = QChar(aa).toLower().unicode();
bb = QChar(bb).toLower().unicode();
result = aa - bb;
++a;
++b;
}
}
return result < 0 ? true : false;
}
/**
* \a real is kinda a hack for the smart search, need a way to match a regexp to an item
* How would you say the best match for Q.*Wiget is QWidget?
*/
QModelIndex IndexListModel::filter(const QString &s, const QString &real)
{
QStringList list;
int goodMatch = -1;
int perfectMatch = -1;
if (s.isEmpty())
perfectMatch = 0;
const QRegExp regExp(s);
QMultiMap<QString, QString>::iterator it = contents.begin();
QString lastKey;
for (; it != contents.end(); ++it) {
if (it.key() == lastKey)
continue;
lastKey = it.key();
const QString key = it.key();
if (key.contains(regExp) || key.contains(s, Qt::CaseInsensitive)) {
list.append(key);
//qDebug() << regExp << regExp.indexIn(s) << s << key << regExp.matchedLength();
if (perfectMatch == -1 && (key.startsWith(real, Qt::CaseInsensitive))) {
if (goodMatch == -1)
goodMatch = list.count() - 1;
if (s.length() == key.length())
perfectMatch = list.count() - 1;
} else if (perfectMatch > -1 && s == key) {
perfectMatch = list.count() - 1;
}
}
}
int bestMatch = perfectMatch;
if (bestMatch == -1)
bestMatch = goodMatch;
bestMatch = qMax(0, bestMatch);
// sort the new list
QString match;
if (bestMatch >= 0 && list.count() > bestMatch)
match = list[bestMatch];
qSort(list.begin(), list.end(), caseInsensitiveLessThan);
setStringList(list);
for (int i = 0; i < list.size(); ++i) {
if (list.at(i) == match){
bestMatch = i;
break;
}
}
return index(bestMatch, 0, QModelIndex());
}
HelpEngine::HelpEngine(QObject *parent, const QString &defaultQtVersionPath)
: QObject(parent)
{
titleMapThread = new TitleMapThread(this);
connect(titleMapThread, SIGNAL(errorOccured(const QString&)),
this, SIGNAL(errorOccured(const QString&)));
connect(titleMapThread, SIGNAL(finished()), this, SLOT(titleMapFinished()));
indexThread = new IndexThread(this);
connect(indexThread, SIGNAL(errorOccured(const QString&)),
this, SIGNAL(errorOccured(const QString&)));
connect(indexThread, SIGNAL(finished()), this, SLOT(indexFinished()));
indexModel = new IndexListModel(this);
Config::loadConfig(defaultQtVersionPath);
cacheFilesPath = QDir::homePath() + QLatin1String("/.assistant");
}
HelpEngine::~HelpEngine()
{
Config::configuration()->save();
}
void HelpEngine::init()
{
}
QString HelpEngine::cacheFilePath() const
{
return cacheFilesPath;
}
IndexListModel *HelpEngine::indices()
{
return indexModel;
}
void HelpEngine::buildContents()
{
contentsOnly = true;
if (!titleMapThread->isRunning()) {
titleMapThread->start(QThread::NormalPriority);
}
}
void HelpEngine::buildIndex()
{
if (!titleMapThread->isRunning()) {
contentsOnly = false;
titleMapThread->start(QThread::NormalPriority);
}
if (!indexThread->isRunning())
indexThread->start(QThread::NormalPriority);
}
void HelpEngine::titleMapFinished()
{
contentList = titleMapThread->contents();
titleMap = titleMapThread->documentTitleMap();
if (contentsOnly) {
contentsOnly = false;
emit contentsInitialized();
}
}
void HelpEngine::indexFinished()
{
indexModel = indexThread->model();
emit indexInitialized();
}
void HelpEngine::removeOldCacheFiles(bool onlyFulltextSearchIndex)
{
if (!verifyDirectory(cacheFilesPath)) {
qWarning("Failed to created assistant directory");
return;
}
QString pname = QLatin1String(".") + Config::configuration()->profileName();
QStringList fileList;
fileList << QLatin1String("indexdb40.dict")
<< QLatin1String("indexdb40.doc");
if (!onlyFulltextSearchIndex)
fileList << QLatin1String("indexdb40") << QLatin1String("contentdb40");
QStringList::iterator it = fileList.begin();
for (; it != fileList.end(); ++it) {
if (QFile::exists(cacheFilesPath + QDir::separator() + *it + pname)) {
QFile f(cacheFilesPath + QDir::separator() + *it + pname);
f.remove();
}
}
}
quint32 HelpEngine::getFileAges()
{
QStringList addDocuFiles = Config::configuration()->docFiles();
QStringList::const_iterator i = addDocuFiles.begin();
quint32 fileAges = 0;
for (; i != addDocuFiles.end(); ++i) {
QFileInfo fi(*i);
if (fi.exists())
fileAges += fi.lastModified().toTime_t();
}
return fileAges;
}
QString HelpEngine::removeAnchorFromLink(const QString &link)
{
int i = link.length();
int j = link.lastIndexOf('/');
int l = link.lastIndexOf(QDir::separator());
if (l > j)
j = l;
if (j > -1) {
QString fileName = link.mid(j+1);
int k = fileName.lastIndexOf('#');
if (k > -1)
i = j + k + 1;
}
return link.left(i);
}
QString HelpEngine::titleOfLink(const QString &link)
{
QString s = HelpEngine::removeAnchorFromLink(link);
s = titleMap[s];
if (s.isEmpty())
return link;
return s;
}
QString HelpEngine::home() const
{
QString link = Config::configuration()->homePage();
if (!link.startsWith(QLatin1String("file:")))