Commit ba876ffd authored by Leandro Melo's avatar Leandro Melo
Browse files

Improve editor's tooltip. Wrapping hack should no longer be necessary.

Also some less significant improvements.
parent b935bca4
......@@ -45,21 +45,12 @@ namespace {
}
HtmlDocExtractor::HtmlDocExtractor() :
m_lengthReference(-1),
m_truncateAtParagraph(false),
m_formatContents(true),
m_extendedExtraction(false)
m_mode(FirstParagraph)
{}
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::setMode(Mode mode)
{ m_mode = mode; }
void HtmlDocExtractor::applyFormatting(const bool format)
{ m_formatContents = format; }
......@@ -67,11 +58,8 @@ void HtmlDocExtractor::applyFormatting(const bool format)
QString HtmlDocExtractor::getClassOrNamespaceBrief(const QString &html, const QString &mark) const
{
QString contents = getContentsByMarks(html, mark + QLatin1String("-brief"), mark);
if (!contents.isEmpty() && m_formatContents) {
if (!contents.isEmpty() && m_formatContents)
contents.remove(QLatin1String("<a href=\"#details\">More...</a>"));
contents.prepend(QLatin1String("<nobr>"));
contents.append(QLatin1String("</nobr>"));
}
processOutput(&contents);
return contents;
......@@ -80,7 +68,7 @@ QString HtmlDocExtractor::getClassOrNamespaceBrief(const QString &html, const QS
QString HtmlDocExtractor::getClassOrNamespaceDescription(const QString &html,
const QString &mark) const
{
if (!m_extendedExtraction)
if (m_mode == FirstParagraph)
return getClassOrNamespaceBrief(html, mark);
QString contents = getContentsByMarks(html, mark + QLatin1String("-description"), mark);
......@@ -191,11 +179,20 @@ void HtmlDocExtractor::processOutput(QString *html) const
if (html->isEmpty())
return;
if (!m_extendedExtraction) {
int paragraph = html->indexOf(QLatin1String("</p>"));
if (paragraph != -1) {
paragraph += 4;
html->truncate(paragraph);
if (m_mode == FirstParagraph) {
int index = html->indexOf(QLatin1String("</p>"));
if (index > 0) {
if (html->at(index - 1) == QLatin1Char('.')) {
index += 4;
html->truncate(index);
} else {
// <p>Paragraphs similar to this. Example:</p>
index = html->lastIndexOf(QLatin1Char('.'), index);
if (index > 0) {
html->truncate(index);
html->append(QLatin1String(".</p>"));
}
}
} 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.
......@@ -216,45 +213,6 @@ void HtmlDocExtractor::processOutput(QString *html) const
stripHeadings(html);
stripImagens(html);
stripEmptyParagraphs(html);
if (!html->startsWith(QLatin1String("<nobr>"))) {
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_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 />"));
const int previousEnd = html->lastIndexOf(exp, m_lengthReference);
if (nextBegin != -1 && previousEnd != -1)
html->truncate(qMin(nextBegin, previousEnd + exp.matchedLength()));
else if (nextBegin != -1 || previousEnd != -1)
html->truncate((nextBegin != -1? nextBegin : previousEnd + exp.matchedLength()));
} else {
html->truncate(m_lengthReference);
}
if (m_formatContents) {
if (html->endsWith(QLatin1String("<br />")))
html->chop(6);
html->append(QLatin1String("<p>...</p>"));
}
}
}
......
......@@ -41,9 +41,12 @@ class QTCREATOR_UTILS_EXPORT HtmlDocExtractor
public:
HtmlDocExtractor();
void extractFirstParagraphOnly();
void extractExtendedContents(const int lengthReference, const bool truncateAtParagraph);
enum Mode {
FirstParagraph,
Extended
};
void setMode(Mode mode);
void applyFormatting(const bool format);
QString getClassOrNamespaceBrief(const QString &html, const QString &mark) const;
......@@ -80,10 +83,8 @@ private:
static void replaceTablesForSimpleLines(QString *html);
static void replaceListsForSimpleLines(QString *html);
int m_lengthReference;
bool m_truncateAtParagraph;
bool m_formatContents;
bool m_extendedExtraction;
Mode m_mode;
};
} // namespace Utils
......
......@@ -106,11 +106,10 @@ void CppHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
}
}
void CppHoverHandler::decorateToolTip(TextEditor::ITextEditor *editor)
void CppHoverHandler::decorateToolTip()
{
CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor->widget());
if (!cppEditor)
return;
if (Qt::mightBeRichText(toolTip()))
setToolTip(Qt::escape(toolTip()));
const TextEditor::HelpItem &help = lastHelpItemIdentified();
if (help.isValid()) {
......@@ -120,11 +119,6 @@ void CppHoverHandler::decorateToolTip(TextEditor::ITextEditor *editor)
appendToolTip(contents);
else
setToolTip(contents);
} else {
QString tip = Qt::escape(toolTip());
tip.prepend(QLatin1String("<nobr>"));
tip.append(QLatin1String("</nobr>"));
setToolTip(tip);
}
addF1ToToolTip();
}
......
......@@ -55,7 +55,7 @@ public:
private:
virtual bool acceptEditor(Core::IEditor *editor);
virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos);
virtual void decorateToolTip(TextEditor::ITextEditor *editor);
virtual void decorateToolTip();
};
} // namespace Internal
......
......@@ -142,25 +142,18 @@ void BaseHoverHandler::process(ITextEditor *editor, int pos)
{
clear();
identifyMatch(editor, pos);
decorateToolTip(editor);
decorateToolTip();
}
void BaseHoverHandler::decorateToolTip(ITextEditor *editor)
void BaseHoverHandler::decorateToolTip()
{
BaseTextEditor *baseEditor = baseTextEditor(editor);
if (!baseEditor)
return;
if (Qt::mightBeRichText(toolTip()))
setToolTip(Qt::escape(toolTip()));
if (lastHelpItemIdentified().isValid()) {
const QString &contents = lastHelpItemIdentified().extractContent(false);
if (!contents.isEmpty()) {
if (!contents.isEmpty())
appendToolTip(contents);
} else {
QString tip = Qt::escape(toolTip());
tip.prepend(QLatin1String("<nobr>"));
tip.append(QLatin1String("</nobr>"));
setToolTip(tip);
}
addF1ToToolTip();
}
}
......
......@@ -80,7 +80,7 @@ private:
virtual bool acceptEditor(Core::IEditor *editor) = 0;
virtual void identifyMatch(ITextEditor *editor, int pos) = 0;
virtual void decorateToolTip(ITextEditor *editor);
virtual void decorateToolTip();
virtual void operateTooltip(ITextEditor *editor, const QPoint &point);
QString m_toolTip;
......
......@@ -81,9 +81,9 @@ QString HelpItem::extractContent(bool extended) const
{
Utils::HtmlDocExtractor htmlExtractor;
if (extended)
htmlExtractor.extractExtendedContents(1500, true);
htmlExtractor.setMode(Utils::HtmlDocExtractor::Extended);
else
htmlExtractor.extractFirstParagraphOnly();
htmlExtractor.setMode(Utils::HtmlDocExtractor::FirstParagraph);
QString contents;
QMap<QString, QUrl> helpLinks = Core::HelpManager::instance()->linksForIdentifier(m_helpId);
......
......@@ -67,8 +67,8 @@ SOURCES += texteditorplugin.cpp \
tooltip/tooltip.cpp \
tooltip/tips.cpp \
tooltip/tipcontents.cpp \
basehoverhandler.cpp \
tooltip/tipfactory.cpp \
basehoverhandler.cpp \
helpitem.cpp
HEADERS += texteditorplugin.h \
......@@ -138,9 +138,10 @@ HEADERS += texteditorplugin.h \
tooltip/tooltip.h \
tooltip/tips.h \
tooltip/tipcontents.h \
basehoverhandler.h \
tooltip/reuse.h \
tooltip/effects.h \
tooltip/tipfactory.h \
basehoverhandler.h \
helpitem.h
FORMS += behaviorsettingspage.ui \
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (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 http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef TOOLTIPREUSE_H
#define TOOLTIPREUSE_H
#include <QtCore/QPoint>
#include <QtCore/QRect>
#include <QtGui/QWidget>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>
namespace TextEditor {
namespace Internal {
inline int screenNumber(const QPoint &pos, QWidget *w)
{
if (QApplication::desktop()->isVirtualDesktop())
return QApplication::desktop()->screenNumber(pos);
else
return QApplication::desktop()->screenNumber(w);
}
inline QRect screenGeometry(const QPoint &pos, QWidget *w)
{
#ifdef Q_WS_MAC
return QApplication::desktop()->availableGeometry(screenNumber(pos, w));
#else
return QApplication::desktop()->screenGeometry(screenNumber(pos, w));
#endif
}
} // namespace Internal
} // namespace TextEditor
#endif // TOOLTIPREUSE_H
......@@ -47,9 +47,5 @@ Internal::QTipLabel *TipFactory::createTip(const TipContent &content, QWidget *w
tip = new TextTip(w);
else if (content.typeId() == ColorContent::COLOR_CONTENT_ID)
tip = new ColorTip(w);
if (tip)
tip->setContent(content);
return tip;
}
......@@ -29,6 +29,7 @@
#include "tips.h"
#include "tipcontents.h"
#include "reuse.h"
#include <QtCore/QRect>
#include <QtGui/QColor>
......@@ -40,6 +41,8 @@
#include <QtGui/QTextDocument>
#include <QtGui/QStylePainter>
#include <QtGui/QStyleOptionFrame>
#include <QtGui/QResizeEvent>
#include <QtGui/QPaintEvent>
namespace TextEditor {
namespace Internal {
......@@ -75,7 +78,6 @@ void QTipLabel::setContent(const TipContent &content)
if (m_tipContent)
delete m_tipContent;
m_tipContent = content.clone();
configure();
}
const TipContent &QTipLabel::content() const
......@@ -90,8 +92,11 @@ ColorTip::ColorTip(QWidget *parent) : QTipLabel(parent)
ColorTip::~ColorTip()
{}
void ColorTip::configure()
void ColorTip::configure(const QPoint &pos, QWidget *w)
{
Q_UNUSED(pos)
Q_UNUSED(w)
update();
}
......@@ -138,17 +143,32 @@ TextTip::TextTip(QWidget *parent) : QTipLabel(parent)
TextTip::~TextTip()
{}
void TextTip::configure()
void TextTip::configure(const QPoint &pos, QWidget *w)
{
const QString &text = static_cast<const TextContent &>(content()).text();
setWordWrap(Qt::mightBeRichText(text));
setText(text);
QFontMetrics fm(font());
QSize extra(1, 0);
// Make it look good with the default ToolTip font on Mac, which has a small descent.
QFontMetrics fm(font());
int extraHeight = 0;
if (fm.descent() == 2 && fm.ascent() >= 11)
++extra.rheight();
resize(sizeHint() + extra);
++extraHeight;
// Try to find a nice width without unnecessary wrapping.
setWordWrap(false);
int tipWidth = sizeHint().width();
const int screenWidth = screenGeometry(pos, w).width();
const int maxDesiredWidth = int(screenWidth * .5);
if (tipWidth > maxDesiredWidth) {
setWordWrap(true);
tipWidth = sizeHint().width();
// If the width is still too large (maybe due to some extremely long word which prevents
// wrapping), the tip is truncated according to the screen.
if (tipWidth > screenWidth)
tipWidth = screenWidth - 10;
}
resize(tipWidth, heightForWidth(tipWidth) + extraHeight);
}
bool TextTip::handleContentReplacement(const TipContent &content) const
......
......@@ -56,7 +56,7 @@ public:
void setContent(const TextEditor::TipContent &content);
const TextEditor::TipContent &content() const;
virtual void configure() = 0;
virtual void configure(const QPoint &pos, QWidget *w) = 0;
virtual bool handleContentReplacement(const TextEditor::TipContent &content) const = 0;
private:
......@@ -70,7 +70,7 @@ public:
ColorTip(QWidget *parent);
virtual ~ColorTip();
virtual void configure();
virtual void configure(const QPoint &pos, QWidget *w);
virtual bool handleContentReplacement(const TipContent &content) const;
private:
......@@ -86,7 +86,7 @@ public:
TextTip(QWidget *parent);
virtual ~TextTip();
virtual void configure();
virtual void configure(const QPoint &pos, QWidget *w);
virtual bool handleContentReplacement(const TipContent &content) const;
private:
......
......@@ -32,11 +32,11 @@
#include "tipcontents.h"
#include "tipfactory.h"
#include "effects.h"
#include "reuse.h"
#include <QtCore/QString>
#include <QtGui/QColor>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>
#include <QtGui/QKeyEvent>
#include <QtGui/QMouseEvent>
......@@ -67,7 +67,8 @@ void ToolTip::show(const QPoint &pos, const TipContent &content, QWidget *w, con
#ifndef Q_WS_WIN
m_tip = m_tipFactory->createTip(content, w);
#else
m_tip = m_tipFactory->createTip(content, QApplication::desktop()->screen(tipScreen(pos,w)));
m_tip = m_tipFactory->createTip(
content, QApplication::desktop()->screen(Internal::screenNumber(pos, w)));
#endif
setUp(pos, content, w, rect);
qApp->installEventFilter(this);
......@@ -96,7 +97,6 @@ bool ToolTip::acceptShow(const TipContent &content,
localPos = w->mapFromGlobal(pos);
if (tipChanged(localPos, content, w)) {
setUp(pos, content, w, rect);
m_tip->setContent(content);
}
return false;
}
......@@ -117,8 +117,12 @@ bool ToolTip::validateContent(const TipContent &content)
void ToolTip::setUp(const QPoint &pos, const TipContent &content, QWidget *w, const QRect &rect)
{
m_tip->setContent(content);
m_tip->configure(pos, w);
placeTip(pos, w);
setTipRect(w, rect);
if (m_hideDelayTimer.isActive())
m_hideDelayTimer.stop();
m_showTimer.start(content.showTime());
......@@ -187,12 +191,7 @@ void ToolTip::hideTipImmediately()
void ToolTip::placeTip(const QPoint &pos, QWidget *w)
{
#ifdef Q_WS_MAC
QRect screen = QApplication::desktop()->availableGeometry(tipScreen(pos, w));
#else
QRect screen = QApplication::desktop()->screenGeometry(tipScreen(pos, w));
#endif
QRect screen = Internal::screenGeometry(pos, w);
QPoint p = pos;
p += QPoint(2,
#ifdef Q_WS_WIN
......@@ -218,14 +217,6 @@ void ToolTip::placeTip(const QPoint &pos, QWidget *w)
m_tip->move(p);
}
int ToolTip::tipScreen(const QPoint &pos, QWidget *w) const
{
if (QApplication::desktop()->isVirtualDesktop())
return QApplication::desktop()->screenNumber(pos);
else
return QApplication::desktop()->screenNumber(w);
}
bool ToolTip::eventFilter(QObject *o, QEvent *event)
{
switch (event->type()) {
......@@ -266,3 +257,13 @@ bool ToolTip::eventFilter(QObject *o, QEvent *event)
}
return false;
}
QFont ToolTip::font() const
{
return QApplication::font("QTipLabel");
}
void ToolTip::setFont(const QFont &font)
{
QApplication::setFont(font, "QTipLabel");
}
......@@ -36,6 +36,7 @@
#include <QtCore/QObject>
#include <QtCore/QTimer>
#include <QtCore/QRect>
#include <QtGui/QFont>
/*
* In its current form QToolTip is not extensible. So this is an attempt to provide a more
......@@ -76,6 +77,9 @@ public:
void hide();
bool isVisible() const;
QFont font() const;
void setFont(const QFont &font);
virtual bool eventFilter(QObject *o, QEvent *event);
private slots:
......@@ -88,7 +92,6 @@ private:
bool tipChanged(const QPoint &pos, const TipContent &content, QWidget *w) const;
void setTipRect(QWidget *w, const QRect &rect);
void placeTip(const QPoint &pos, QWidget *w);
int tipScreen(const QPoint &pos, QWidget *w) const;
void showTip();
void hideTipWithDelay();
......
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