Commit da14d861 authored by Jarek Kobus's avatar Jarek Kobus

Implement context help for pro file editor

Task-number: QTCREATORBUG-6325
Change-Id: Ie8b2eb582eb527eac6af56d0c69a8ae1dafdc1df
Reviewed-by: default avatarLeandro Melo <leandro.melo@nokia.com>
parent 8fcb4d80
......@@ -147,10 +147,10 @@ QString HtmlDocExtractor::getQmlComponentDescription(const QString &html, const
QString HtmlDocExtractor::getQmlPropertyDescription(const QString &html, const QString &mark) const
{
QString startMark = QString("<a name=\"%1-prop\">").arg(mark);
QString startMark = QString::fromLatin1("<a name=\"%1-prop\">").arg(mark);
int index = html.indexOf(startMark);
if (index == -1) {
startMark = QString("<a name=\"%1-signal\">").arg(mark);
startMark = QString::fromLatin1("<a name=\"%1-signal\">").arg(mark);
index = html.indexOf(startMark);
}
if (index == -1)
......@@ -166,6 +166,42 @@ QString HtmlDocExtractor::getQmlPropertyDescription(const QString &html, const Q
return contents;
}
QString HtmlDocExtractor::getQMakeVariableOrFunctionDescription(const QString &html,
const QString &mark) const
{
const QString startMark = QString::fromLatin1("<a name=\"%1\"></a>").arg(mark);
int index = html.indexOf(startMark);
if (index == -1)
return QString();
QString contents = html.mid(index + startMark.size());
index = contents.indexOf(QLatin1String("<!-- @@@qmake"));
if (index == -1)
return QString();
contents = contents.left(index);
processOutput(&contents);
return contents;
}
QString HtmlDocExtractor::getQMakeFunctionId(const QString &html,
const QString &mark) const
{
const QString startMark = QString::fromLatin1("<a name=\"%1-").arg(mark);
const int startIndex = html.indexOf(startMark);
if (startIndex == -1)
return QString();
const int startKeyIndex = html.indexOf(mark, startIndex);
const QString endMark = QLatin1String("\"></a>");
const int endKeyIndex = html.indexOf(endMark, startKeyIndex);
if (endKeyIndex == -1)
return QString();
return html.mid(startKeyIndex, endKeyIndex - startKeyIndex);
}
QString HtmlDocExtractor::getClassOrNamespaceMemberDescription(const QString &html,
const QString &startMark,
const QString &endMark) const
......@@ -206,9 +242,18 @@ void HtmlDocExtractor::processOutput(QString *html) const
if (m_mode == FirstParagraph) {
// Try to get the entire first paragraph, but if one is not found or if its opening
// tag is not in the very beginning (using an empirical value as the limit) the html
// is cleared to avoid too much content.
// is cleared to avoid too much content. In case the first paragraph looks like:
// <p><i>This is only used on the Maemo platform.</i></p>
// or: <p><tt>This is used on Windows only.</tt></p>
// or: <p>[Conditional]</p>
// include also the next paragraph.
int index = html->indexOf(QLatin1String("<p>"));
if (index != -1 && index < 400) {
if (html->indexOf(QLatin1String("<p><i>")) == index ||
html->indexOf(QLatin1String("<p><tt>")) == index ||
html->indexOf(QLatin1String("<p>[Conditional]</p>")) == index)
index = html->indexOf(QLatin1String("<p>"), index + 6); // skip the first paragraph
index = html->indexOf(QLatin1String("</p>"), index + 3);
if (index != -1) {
// Most paragraphs end with a period, but there are cases without punctuation
......
......@@ -62,6 +62,10 @@ public:
const bool mainOverload = true) const;
QString getQmlComponentDescription(const QString &html, const QString &mark) const;
QString getQmlPropertyDescription(const QString &html, const QString &mark) const;
QString getQMakeVariableOrFunctionDescription(const QString &html,
const QString &mark) const;
QString getQMakeFunctionId(const QString &html,
const QString &mark) const;
private:
QString getClassOrNamespaceMemberDescription(const QString &html,
......
......@@ -883,6 +883,12 @@ void HelpPlugin::activateContext()
if (IContext *context = m_core->currentContextObject()) {
m_idFromContext = context->contextHelpId();
links = Core::HelpManager::instance()->linksForIdentifier(m_idFromContext);
if (links.isEmpty()) {
// Maybe this is already an URL...
QUrl url(m_idFromContext);
if (url.isValid())
links.insert(m_idFromContext, m_idFromContext);
}
}
if (HelpViewer* viewer = viewerForContextMode()) {
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** 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.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "profilehoverhandler.h"
#include "profileeditor.h"
#include "profilekeywords.h"
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/helpmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/helpitem.h>
#include <texteditor/tooltip/tooltip.h>
#include <utils/htmldocextractor.h>
#include <QtGui/QTextCursor>
#include <QtGui/QTextBlock>
#include <QtCore/QUrl>
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
using namespace Core;
ProFileHoverHandler::ProFileHoverHandler(QObject *parent)
: BaseHoverHandler(parent),
m_manualKind(UnknownManual)
{
}
ProFileHoverHandler::~ProFileHoverHandler()
{}
bool ProFileHoverHandler::acceptEditor(IEditor *editor)
{
if (qobject_cast<ProFileEditor *>(editor) != 0)
return true;
return false;
}
void ProFileHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
{
m_docFragment = QString();
m_manualKind = UnknownManual;
if (ProFileEditorWidget *proFileEditor = qobject_cast<ProFileEditorWidget *>(editor->widget())) {
if (!proFileEditor->extraSelectionTooltip(pos).isEmpty()) {
setToolTip(proFileEditor->extraSelectionTooltip(pos));
} else {
QTextDocument *document = proFileEditor->document();
QTextBlock block = document->findBlock(pos);
identifyQMakeKeyword(block.text(), pos - block.position());
if (m_manualKind != UnknownManual) {
QUrl url(QString::fromLatin1("qthelp://com.trolltech.qmake/qdoc/qmake-%1-reference.html#%2")
.arg(manualName()).arg(m_docFragment));
setLastHelpItemIdentified(TextEditor::HelpItem(url.toString(),
m_docFragment, TextEditor::HelpItem::QMakeVariableOfFunction));
} else {
// General qmake manual will be shown outside any function or variable
setLastHelpItemIdentified(TextEditor::HelpItem(QLatin1String("qmake"),
TextEditor::HelpItem::Unknown));
}
}
}
}
void ProFileHoverHandler::identifyQMakeKeyword(const QString &text, int pos)
{
if (text.isEmpty())
return;
QString buf;
for (int i = 0; i < text.length(); ++i) {
const QChar c = text.at(i);
bool checkBuffer = false;
if (c.isLetter() || c == QLatin1Char('_') || c == QLatin1Char('.') || c.isDigit()) {
buf += c;
if (i == text.length() - 1)
checkBuffer = true;
} else {
checkBuffer = true;
}
if (checkBuffer) {
if (!buf.isEmpty()) {
if ((i >= pos) && (i - buf.size() <= pos)) {
if (ProFileKeywords::isFunction(buf))
identifyDocFragment(FunctionManual, buf);
else if (ProFileKeywords::isVariable(buf))
identifyDocFragment(VariableManual, buf);
break;
}
buf.clear();
} else {
if (i >= pos)
break; // we are after the tooltip pos
}
if (c == '#')
break; // comment start
}
}
}
QString ProFileHoverHandler::manualName() const
{
if (m_manualKind == FunctionManual)
return QLatin1String("function");
else if (m_manualKind == VariableManual)
return QLatin1String("variable");
return QString();
}
void ProFileHoverHandler::identifyDocFragment(ProFileHoverHandler::ManualKind manualKind,
const QString &keyword)
{
m_manualKind = manualKind;
m_docFragment = keyword.toLower();
// Special case: _PRO_FILE_ and _PRO_FILE_PWD_ ids
// don't have starting and ending '_'.
if (m_docFragment.startsWith(QLatin1Char('_')))
m_docFragment = m_docFragment.mid(1);
if (m_docFragment.endsWith(QLatin1Char('_')))
m_docFragment = m_docFragment.left(m_docFragment.size() - 1);
m_docFragment.replace(QLatin1Char('.'), QLatin1Char('-'));
m_docFragment.replace(QLatin1Char('_'), QLatin1Char('-'));
if (m_manualKind == FunctionManual) {
QUrl url(QString::fromLatin1("qthelp://com.trolltech.qmake/qdoc/qmake-%1-reference.html").arg(manualName()));
const QByteArray &html = Core::HelpManager::instance()->fileData(url);
Utils::HtmlDocExtractor htmlExtractor;
htmlExtractor.setMode(Utils::HtmlDocExtractor::FirstParagraph);
// Document fragment of qmake function is retrieved from docs.
// E.g. in case of the keyword "find" the document fragment
// parsed from docs is "find-variablename-substr".
m_docFragment = htmlExtractor.getQMakeFunctionId(html, m_docFragment);
}
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** 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.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef PROFILEHOVERHANDLER_H
#define PROFILEHOVERHANDLER_H
#include <texteditor/basehoverhandler.h>
#include <QtCore/QObject>
QT_BEGIN_NAMESPACE
class QUrl;
QT_END_NAMESPACE
namespace Core {
class IEditor;
}
namespace TextEditor {
class ITextEditor;
}
namespace Qt4ProjectManager {
namespace Internal {
class ProFileHoverHandler : public TextEditor::BaseHoverHandler
{
Q_OBJECT
public:
ProFileHoverHandler(QObject *parent = 0);
virtual ~ProFileHoverHandler();
signals:
void creatorHelpRequested(const QUrl &url);
private:
virtual bool acceptEditor(Core::IEditor *editor);
virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos);
void identifyQMakeKeyword(const QString &text, int pos);
enum ManualKind {
VariableManual,
FunctionManual,
UnknownManual
};
QString manualName() const;
void identifyDocFragment(ManualKind manualKind,
const QString &keyword);
QString m_docFragment;
ManualKind m_manualKind;
};
} // namespace Internal
} // namespace Qt4ProjectManager
#endif // PROFILEHOVERHANDLER_H
......@@ -13,6 +13,7 @@ HEADERS += \
profileeditor.h \
profilehighlighter.h \
profileeditorfactory.h \
profilehoverhandler.h \
wizards/qtprojectparameters.h \
wizards/guiappwizard.h \
wizards/mobileapp.h \
......@@ -75,6 +76,7 @@ SOURCES += qt4projectmanagerplugin.cpp \
profileeditor.cpp \
profilehighlighter.cpp \
profileeditorfactory.cpp \
profilehoverhandler.cpp \
wizards/qtprojectparameters.cpp \
wizards/guiappwizard.cpp \
wizards/mobileapp.cpp \
......
......@@ -47,6 +47,7 @@
#include "wizards/html5appwizard.h"
#include "customwidgetwizard/customwidgetwizard.h"
#include "profileeditorfactory.h"
#include "profilehoverhandler.h"
#include "qt4projectmanagerconstants.h"
#include "qt4project.h"
#include "profileeditor.h"
......@@ -159,6 +160,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
addAutoReleasedObject(new WinCeQtVersionFactory);
addAutoReleasedObject(new ProFileCompletionAssistProvider);
addAutoReleasedObject(new ProFileHoverHandler(this));
// TODO reenable
//m_embeddedPropertiesPage = new EmbeddedPropertiesPage;
......
......@@ -157,8 +157,8 @@ void BaseHoverHandler::decorateToolTip()
if (!contents.isEmpty()) {
setToolTip(Qt::escape(toolTip()));
appendToolTip(contents);
addF1ToToolTip();
}
addF1ToToolTip();
}
}
......
......@@ -61,8 +61,6 @@ public:
private slots:
void editorOpened(Core::IEditor *editor);
public slots:
void showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos);
void updateContextHelpId(TextEditor::ITextEditor *editor, int pos);
......
......@@ -77,6 +77,8 @@ bool HelpItem::isValid() const
{
if (!Core::HelpManager::instance()->linksForIdentifier(m_helpId).isEmpty())
return true;
if (QUrl(m_helpId).isValid())
return true;
return false;
}
......@@ -90,6 +92,12 @@ QString HelpItem::extractContent(bool extended) const
QString contents;
QMap<QString, QUrl> helpLinks = Core::HelpManager::instance()->linksForIdentifier(m_helpId);
if (helpLinks.isEmpty()) {
// Maybe this is already an URL...
QUrl url(m_helpId);
if (url.isValid())
helpLinks.insert(m_helpId, m_helpId);
}
foreach (const QUrl &url, helpLinks) {
const QByteArray &html = Core::HelpManager::instance()->fileData(url);
switch (m_category) {
......@@ -117,6 +125,9 @@ QString HelpItem::extractContent(bool extended) const
case QmlProperty:
contents = htmlExtractor.getQmlPropertyDescription(html, m_docMark);
break;
case QMakeVariableOfFunction:
contents = htmlExtractor.getQMakeVariableOrFunctionDescription(html, m_docMark);
break;
default:
break;
......
......@@ -51,6 +51,7 @@ public:
Function,
QmlComponent,
QmlProperty,
QMakeVariableOfFunction,
Unknown
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment