Commit 0ccdbbc9 authored by Leandro Melo's avatar Leandro Melo
Browse files

C++ tooltip: Integration with Qt docs always on (for showing brief descriptions).

The old integration option is now used to switch to extended descriptions.
parent 5a1983f9
......@@ -47,16 +47,21 @@ namespace {
HtmlDocExtractor::HtmlDocExtractor() :
m_lengthReference(-1),
m_truncateAtParagraph(false),
m_formatContents(true)
m_formatContents(true),
m_extendedExtraction(false)
{}
void HtmlDocExtractor::setLengthReference(const int length, const bool truncateAtParagraph)
void HtmlDocExtractor::extractFirstParagraphOnly()
{ m_extendedExtraction = false; }
void HtmlDocExtractor::extractExtendedContents(const int length, const bool truncateAtParagraph)
{
m_lengthReference = length;
m_truncateAtParagraph = truncateAtParagraph;
m_extendedExtraction = true;
}
void HtmlDocExtractor::setFormatContents(const bool format)
void HtmlDocExtractor::applyFormatting(const bool format)
{ m_formatContents = format; }
QString HtmlDocExtractor::getClassOrNamespaceBrief(const QString &html, const QString &mark) const
......@@ -66,7 +71,6 @@ QString HtmlDocExtractor::getClassOrNamespaceBrief(const QString &html, const QS
contents.remove(QLatin1String("<a href=\"#details\">More...</a>"));
contents.prepend(QLatin1String("<nobr>"));
contents.append(QLatin1String("</nobr>"));
formatContents(&contents);
}
return contents;
......@@ -75,6 +79,9 @@ QString HtmlDocExtractor::getClassOrNamespaceBrief(const QString &html, const QS
QString HtmlDocExtractor::getClassOrNamespaceDescription(const QString &html,
const QString &mark) const
{
if (!m_extendedExtraction)
return getClassOrNamespaceBrief(html, mark);
QString contents = getContentsByMarks(html, mark + QLatin1String("-description"), mark);
if (!contents.isEmpty() && m_formatContents) {
contents.remove(QLatin1String("Detailed Description"));
......@@ -178,8 +185,18 @@ QString HtmlDocExtractor::getContentsByMarks(const QString &html,
void HtmlDocExtractor::formatContents(QString *html) const
{
if (html->isEmpty())
return;
if (!m_extendedExtraction) {
int paragraph = html->indexOf(QLatin1String("</p>"));
if (paragraph != -1) {
paragraph += 4;
html->truncate(paragraph);
} else {
// Some enumerations don't have paragraphs and just a table with the items. In such
// cases the the html is cleared to avoid showing more that desired.
html->clear();
return;
}
}
if (m_formatContents) {
stripBold(html);
......@@ -192,9 +209,28 @@ void HtmlDocExtractor::formatContents(QString *html) const
stripTagsStyles(html);
stripHeadings(html);
stripImagens(html);
stripEmptyParagraphs(html);
if (!m_extendedExtraction) {
if (!html->endsWith(QLatin1String(".</p>"))) {
// <p>For paragraphs similar to this. Example:</p>
const int lastDot = html->lastIndexOf(QLatin1Char('.'));
if (lastDot != -1) {
html->truncate(lastDot);
html->append(QLatin1String(".</p>"));
}
}
}
const int noBreakLimit = 140;
const int paragraph = html->indexOf(QLatin1String("<p>"));
if (paragraph > 0 && paragraph <= noBreakLimit) {
html->insert(paragraph, QLatin1String("</nobr>"));
html->prepend(QLatin1String("<nobr>"));
}
}
if (m_lengthReference > -1 && html->length() > m_lengthReference) {
if (m_extendedExtraction && m_lengthReference > -1 && html->length() > m_lengthReference) {
if (m_truncateAtParagraph) {
const int nextBegin = html->indexOf(QLatin1String("<p>"), m_lengthReference);
QRegExp exp = createMinimalExp(QLatin1String("</p>|<br />"));
......@@ -262,6 +298,11 @@ void HtmlDocExtractor::stripBold(QString *html)
html->remove(QLatin1String("</b>"));
}
void HtmlDocExtractor::stripEmptyParagraphs(QString *html)
{
html->remove(QLatin1String("<p></p>"));
}
void HtmlDocExtractor::replaceNonStyledHeadingsForBold(QString *html)
{
const QRegExp &hStart = createMinimalExp(QLatin1String("<h\\d{1}>"));
......
......@@ -41,8 +41,10 @@ class QTCREATOR_UTILS_EXPORT HtmlDocExtractor
public:
HtmlDocExtractor();
void setLengthReference(const int reference, const bool truncateAtParagraph);
void setFormatContents(const bool format);
void extractFirstParagraphOnly();
void extractExtendedContents(const int lengthReference, const bool truncateAtParagraph);
void applyFormatting(const bool format);
QString getClassOrNamespaceBrief(const QString &html, const QString &mark) const;
QString getClassOrNamespaceDescription(const QString &html, const QString &mark) const;
......@@ -72,6 +74,7 @@ private:
static void stripTeletypes(QString *html);
static void stripImagens(QString *html);
static void stripBold(QString *html);
static void stripEmptyParagraphs(QString *html);
static void replaceNonStyledHeadingsForBold(QString *html);
static void replaceTablesForSimpleLines(QString *html);
static void replaceListsForSimpleLines(QString *html);
......@@ -79,6 +82,7 @@ private:
int m_lengthReference;
bool m_truncateAtParagraph;
bool m_formatContents;
bool m_extendedExtraction;
};
} // namespace Utils
......
......@@ -118,8 +118,6 @@ CppHoverHandler::CppHoverHandler(QObject *parent)
m_modelManager =
ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
m_htmlDocExtractor.setLengthReference(1000, true);
// Listen for editor opened events in order to connect to tooltip/helpid requests
connect(ICore::instance()->editorManager(), SIGNAL(editorOpened(Core::IEditor *)),
this, SLOT(editorOpened(Core::IEditor *)));
......@@ -174,9 +172,9 @@ void CppHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint
QToolTip::hideText();
} else {
if (!m_classHierarchy.isEmpty())
generateDiagramTooltip(baseEditor->displaySettings().m_integrateDocsIntoTooltips);
generateDiagramTooltip(baseEditor->displaySettings().m_extendTooltips);
else
generateNormalTooltip(baseEditor->displaySettings().m_integrateDocsIntoTooltips);
generateNormalTooltip(baseEditor->displaySettings().m_extendTooltips);
if (m_matchingHelpCandidate != -1)
addF1ToTooltip();
......@@ -384,15 +382,20 @@ bool CppHoverHandler::helpIdExists(const QString &helpId) const
return false;
}
QString CppHoverHandler::getDocContents() const
QString CppHoverHandler::getDocContents(const bool extended)
{
Q_ASSERT(m_matchingHelpCandidate >= 0);
return getDocContents(m_helpCandidates.at(m_matchingHelpCandidate));
return getDocContents(m_helpCandidates.at(m_matchingHelpCandidate), extended);
}
QString CppHoverHandler::getDocContents(const HelpCandidate &help) const
QString CppHoverHandler::getDocContents(const HelpCandidate &help, const bool extended)
{
if (extended)
m_htmlDocExtractor.extractExtendedContents(1500, true);
else
m_htmlDocExtractor.extractFirstParagraphOnly();
QString contents;
QMap<QString, QUrl> helpLinks =
Core::HelpManager::instance()->linksForIdentifier(help.m_helpId);
......@@ -427,7 +430,7 @@ QString CppHoverHandler::getDocContents(const HelpCandidate &help) const
return contents;
}
void CppHoverHandler::generateDiagramTooltip(const bool integrateDocs)
void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
{
QString clazz = m_toolTip;
......@@ -457,75 +460,71 @@ void CppHoverHandler::generateDiagramTooltip(const bool integrateDocs)
diagram.append(QLatin1String("</table>"));
m_toolTip = diagram;
if (integrateDocs) {
if (m_matchingHelpCandidate != -1) {
m_toolTip.append(getDocContents());
} else {
// Look for documented base classes. Diagram the nearest one or the nearest ones (in
// the case there are many at the same level).
int helpLevel = 0;
QList<int> baseClassesWithHelp;
for (int i = 0; i < m_classHierarchy.size(); ++i) {
const QStringList &hierarchy = m_classHierarchy.at(i);
if (helpLevel != 0 && hierarchy.size() != helpLevel)
break;
const QString &name = hierarchy.last();
if (helpIdExists(name)) {
baseClassesWithHelp.append(i);
if (helpLevel == 0)
helpLevel = hierarchy.size();
}
if (m_matchingHelpCandidate != -1) {
m_toolTip.append(getDocContents(extendTooltips));
} else {
// Look for documented base classes. Diagram the nearest one or the nearest ones (in
// the case there are many at the same level).
int helpLevel = 0;
QList<int> baseClassesWithHelp;
for (int i = 0; i < m_classHierarchy.size(); ++i) {
const QStringList &hierarchy = m_classHierarchy.at(i);
if (helpLevel != 0 && hierarchy.size() != helpLevel)
break;
const QString &name = hierarchy.last();
if (helpIdExists(name)) {
baseClassesWithHelp.append(i);
if (helpLevel == 0)
helpLevel = hierarchy.size();
}
}
if (!baseClassesWithHelp.isEmpty()) {
// Choose the first one as the help match.
QString base = m_classHierarchy.at(baseClassesWithHelp.at(0)).last();
HelpCandidate help(base, base, HelpCandidate::ClassOrNamespace);
m_helpCandidates.append(help);
m_matchingHelpCandidate = m_helpCandidates.size() - 1;
if (!baseClassesWithHelp.isEmpty()) {
// Choose the first one as the help match.
QString base = m_classHierarchy.at(baseClassesWithHelp.at(0)).last();
HelpCandidate help(base, base, HelpCandidate::ClassOrNamespace);
m_helpCandidates.append(help);
m_matchingHelpCandidate = m_helpCandidates.size() - 1;
if (baseClassesWithHelp.size() == 1 && helpLevel == 1) {
m_toolTip.append(getDocContents(help));
} else {
foreach (int hierarchyIndex, baseClassesWithHelp) {
m_toolTip.append(QLatin1String("<p>"));
const QStringList &hierarchy = m_classHierarchy.at(hierarchyIndex);
Q_ASSERT(helpLevel <= hierarchy.size());
// Following contents are inside tables so they are on the exact same
// alignment as the top level diagram.
diagram = QString(QLatin1String("<table><tr><td>%1</td>")).arg(clazz);
for (int i = 0; i < helpLevel; ++i) {
diagram.append(
QLatin1String("<td><img src=\":/cppeditor/images/rightarrow.png\">"
"</td><td>") %
hierarchy.at(i) %
QLatin1String("</td>"));
}
diagram.append(QLatin1String("</tr></table>"));
base = hierarchy.at(helpLevel - 1);
QString contents =
getDocContents(HelpCandidate(base, base, HelpCandidate::Brief));
if (!contents.isEmpty()) {
m_toolTip.append(diagram % QLatin1String("<table><tr><td>") %
contents % QLatin1String("</td></tr></table>"));
}
m_toolTip.append(QLatin1String("</p>"));
if (baseClassesWithHelp.size() == 1 && helpLevel == 1) {
m_toolTip.append(getDocContents(help, extendTooltips));
} else {
foreach (int hierarchyIndex, baseClassesWithHelp) {
m_toolTip.append(QLatin1String("<p>"));
const QStringList &hierarchy = m_classHierarchy.at(hierarchyIndex);
Q_ASSERT(helpLevel <= hierarchy.size());
// Following contents are inside tables so they are on the exact same
// alignment as the top level diagram.
diagram = QString(QLatin1String("<table><tr><td>%1</td>")).arg(clazz);
for (int i = 0; i < helpLevel; ++i) {
diagram.append(
QLatin1String("<td><img src=\":/cppeditor/images/rightarrow.png\">"
"</td><td>") %
hierarchy.at(i) %
QLatin1String("</td>"));
}
diagram.append(QLatin1String("</tr></table>"));
base = hierarchy.at(helpLevel - 1);
QString contents =
getDocContents(HelpCandidate(base, base, HelpCandidate::Brief), false);
if (!contents.isEmpty()) {
m_toolTip.append(diagram % QLatin1String("<table><tr><td>") %
contents % QLatin1String("</td></tr></table>"));
}
m_toolTip.append(QLatin1String("</p>"));
}
}
}
}
}
void CppHoverHandler::generateNormalTooltip(const bool integrateDocs)
void CppHoverHandler::generateNormalTooltip(const bool extendTooltips)
{
if (m_matchingHelpCandidate != -1) {
QString contents;
if (integrateDocs)
contents = getDocContents();
const QString &contents = getDocContents(extendTooltips);
if (!contents.isEmpty()) {
HelpCandidate::Category cat = m_helpCandidates.at(m_matchingHelpCandidate).m_category;
if (cat == HelpCandidate::ClassOrNamespace)
......
......@@ -107,11 +107,11 @@ private:
void evaluateHelpCandidates();
bool helpIdExists(const QString &helpId) const;
QString getDocContents() const;
QString getDocContents(const HelpCandidate &helpCandidate) const;
QString getDocContents(const bool extended);
QString getDocContents(const HelpCandidate &helpCandidate, const bool extended);
void generateDiagramTooltip(const bool integrateDocs);
void generateNormalTooltip(const bool integrateDocs);
void generateDiagramTooltip(const bool extendTooltips);
void generateNormalTooltip(const bool extendTooltips);
void addF1ToTooltip();
static TextEditor::BaseTextEditor *baseTextEditor(TextEditor::ITextEditor *editor);
......
......@@ -44,7 +44,7 @@ static const char * const animateMatchingParenthesesKey= "AnimateMatchingParenth
static const char * const markTextChangesKey = "MarkTextChanges";
static const char * const autoFoldFirstCommentKey = "AutoFoldFirstComment";
static const char * const centerCursorOnScrollKey = "CenterCursorOnScroll";
static const char * const integrateDocsIntoTooltips = "IntegrateDocsIntoTooltips";
static const char * const extendTooltips = "ExtendTooltips";
static const char * const groupPostfix = "DisplaySettings";
namespace TextEditor {
......@@ -62,7 +62,7 @@ DisplaySettings::DisplaySettings() :
m_markTextChanges(true),
m_autoFoldFirstComment(true),
m_centerCursorOnScroll(false),
m_integrateDocsIntoTooltips(true)
m_extendTooltips(false)
{
}
......@@ -84,7 +84,7 @@ void DisplaySettings::toSettings(const QString &category, QSettings *s) const
s->setValue(QLatin1String(markTextChangesKey), m_markTextChanges);
s->setValue(QLatin1String(autoFoldFirstCommentKey), m_autoFoldFirstComment);
s->setValue(QLatin1String(centerCursorOnScrollKey), m_centerCursorOnScroll);
s->setValue(QLatin1String(integrateDocsIntoTooltips), m_integrateDocsIntoTooltips);
s->setValue(QLatin1String(extendTooltips), m_extendTooltips);
s->endGroup();
}
......@@ -109,7 +109,7 @@ void DisplaySettings::fromSettings(const QString &category, const QSettings *s)
m_markTextChanges = s->value(group + QLatin1String(markTextChangesKey), m_markTextChanges).toBool();
m_autoFoldFirstComment = s->value(group + QLatin1String(autoFoldFirstCommentKey), m_autoFoldFirstComment).toBool();
m_centerCursorOnScroll = s->value(group + QLatin1String(centerCursorOnScrollKey), m_centerCursorOnScroll).toBool();
m_integrateDocsIntoTooltips = s->value(group + QLatin1String(integrateDocsIntoTooltips), m_integrateDocsIntoTooltips).toBool();
m_extendTooltips = s->value(group + QLatin1String(extendTooltips), m_extendTooltips).toBool();
}
bool DisplaySettings::equals(const DisplaySettings &ds) const
......@@ -126,7 +126,7 @@ bool DisplaySettings::equals(const DisplaySettings &ds) const
&& m_markTextChanges == ds.m_markTextChanges
&& m_autoFoldFirstComment== ds.m_autoFoldFirstComment
&& m_centerCursorOnScroll == ds.m_centerCursorOnScroll
&& m_integrateDocsIntoTooltips == ds.m_integrateDocsIntoTooltips
&& m_extendTooltips == ds.m_extendTooltips
;
}
......
......@@ -57,7 +57,7 @@ struct TEXTEDITOR_EXPORT DisplaySettings
bool m_markTextChanges;
bool m_autoFoldFirstComment;
bool m_centerCursorOnScroll;
bool m_integrateDocsIntoTooltips;
bool m_extendTooltips;
bool equals(const DisplaySettings &ds) const;
};
......
......@@ -94,7 +94,7 @@ QWidget *DisplaySettingsPage::createPage(QWidget *parent)
<< ' ' << m_d->m_page.enableTextWrapping->text()
<< ' ' << m_d->m_page.autoFoldFirstComment->text()
<< ' ' << m_d->m_page.centerOnScroll->text()
<< ' ' << m_d->m_page.integrateDocsIntoTooltips->text();
<< ' ' << m_d->m_page.extendTooltips->text();
m_d->m_searchKeywords.remove(QLatin1Char('&'));
}
return w;
......@@ -122,7 +122,7 @@ void DisplaySettingsPage::settingsFromUI(DisplaySettings &displaySettings) const
displaySettings.m_markTextChanges = m_d->m_page.markTextChanges->isChecked();
displaySettings.m_autoFoldFirstComment = m_d->m_page.autoFoldFirstComment->isChecked();
displaySettings.m_centerCursorOnScroll = m_d->m_page.centerOnScroll->isChecked();
displaySettings.m_integrateDocsIntoTooltips = m_d->m_page.integrateDocsIntoTooltips->isChecked();
displaySettings.m_extendTooltips = m_d->m_page.extendTooltips->isChecked();
}
void DisplaySettingsPage::settingsToUI()
......@@ -140,7 +140,7 @@ void DisplaySettingsPage::settingsToUI()
m_d->m_page.markTextChanges->setChecked(displaySettings.m_markTextChanges);
m_d->m_page.autoFoldFirstComment->setChecked(displaySettings.m_autoFoldFirstComment);
m_d->m_page.centerOnScroll->setChecked(displaySettings.m_centerCursorOnScroll);
m_d->m_page.integrateDocsIntoTooltips->setChecked(displaySettings.m_integrateDocsIntoTooltips);
m_d->m_page.extendTooltips->setChecked(displaySettings.m_extendTooltips);
}
const DisplaySettings &DisplaySettingsPage::displaySettings() const
......
......@@ -97,9 +97,9 @@
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="integrateDocsIntoTooltips">
<widget class="QCheckBox" name="extendTooltips">
<property name="text">
<string>Integrate Qt docs into tooltips</string>
<string>Extend tooltips for Qt 4.7 (or later) docs</string>
</property>
</widget>
</item>
......
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