From 0ccdbbc91d7b0fe9bf11558196ba87ccab31ed40 Mon Sep 17 00:00:00 2001 From: Leandro Melo <leandro.melo@nokia.com> Date: Thu, 22 Jul 2010 12:00:21 +0200 Subject: [PATCH] C++ tooltip: Integration with Qt docs always on (for showing brief descriptions). The old integration option is now used to switch to extended descriptions. --- src/libs/utils/htmldocextractor.cpp | 55 +++++++- src/libs/utils/htmldocextractor.h | 8 +- src/plugins/cppeditor/cpphoverhandler.cpp | 131 +++++++++--------- src/plugins/cppeditor/cpphoverhandler.h | 8 +- src/plugins/texteditor/displaysettings.cpp | 10 +- src/plugins/texteditor/displaysettings.h | 2 +- .../texteditor/displaysettingspage.cpp | 6 +- src/plugins/texteditor/displaysettingspage.ui | 4 +- 8 files changed, 134 insertions(+), 90 deletions(-) diff --git a/src/libs/utils/htmldocextractor.cpp b/src/libs/utils/htmldocextractor.cpp index cbaa37fc477..83b8afafe3e 100644 --- a/src/libs/utils/htmldocextractor.cpp +++ b/src/libs/utils/htmldocextractor.cpp @@ -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}>")); diff --git a/src/libs/utils/htmldocextractor.h b/src/libs/utils/htmldocextractor.h index 67f23df369a..02706dc15a4 100644 --- a/src/libs/utils/htmldocextractor.h +++ b/src/libs/utils/htmldocextractor.h @@ -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 diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index a8848e8752b..3c1c36cb29d 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -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) diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cppeditor/cpphoverhandler.h index 464fda0e4f9..094bf68b4b2 100644 --- a/src/plugins/cppeditor/cpphoverhandler.h +++ b/src/plugins/cppeditor/cpphoverhandler.h @@ -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); diff --git a/src/plugins/texteditor/displaysettings.cpp b/src/plugins/texteditor/displaysettings.cpp index 575d2fd2289..24232bc13b6 100644 --- a/src/plugins/texteditor/displaysettings.cpp +++ b/src/plugins/texteditor/displaysettings.cpp @@ -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 ; } diff --git a/src/plugins/texteditor/displaysettings.h b/src/plugins/texteditor/displaysettings.h index a421ea7ee3a..424a276e46a 100644 --- a/src/plugins/texteditor/displaysettings.h +++ b/src/plugins/texteditor/displaysettings.h @@ -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; }; diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp index 27d00766c57..92561c9510b 100644 --- a/src/plugins/texteditor/displaysettingspage.cpp +++ b/src/plugins/texteditor/displaysettingspage.cpp @@ -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 diff --git a/src/plugins/texteditor/displaysettingspage.ui b/src/plugins/texteditor/displaysettingspage.ui index 28e6b71397a..06d553c7e36 100644 --- a/src/plugins/texteditor/displaysettingspage.ui +++ b/src/plugins/texteditor/displaysettingspage.ui @@ -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> -- GitLab