Warning, file /sdk/cervisia/tooltip.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  * Copyright (c) 2004-2008 André Wöbbeking <Woebbeking@kde.org>
0003  *
0004  * This program is free software; you can redistribute it and/or modify
0005  * it under the terms of the GNU General Public License as published by
0006  * the Free Software Foundation; either version 2 of the License, or
0007  * (at your option) any later version.
0008  *
0009  * This program is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  * GNU General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU General Public License
0015  * along with this program; if not, write to the Free Software
0016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0017  */
0018 
0019 #include "tooltip.h"
0020 
0021 #include <QApplication>
0022 #include <QDesktopWidget>
0023 #include <qevent.h>
0024 #include <qtextdocument.h>
0025 #include <qtooltip.h>
0026 
0027 namespace Cervisia
0028 {
0029 
0030 static QString truncateLines(const QString &, const QFontMetrics &, const QSize &);
0031 static QString truncateLines(const QString &, const QFont &, const QPoint &, const QRect &);
0032 
0033 ToolTip::ToolTip(QWidget *widget)
0034     : QObject(widget)
0035 {
0036     widget->installEventFilter(this);
0037 }
0038 
0039 bool ToolTip::eventFilter(QObject *watched, QEvent *event)
0040 {
0041     if ((watched == parent()) && (event->type() == QEvent::ToolTip)) {
0042         const QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
0043 
0044         QRect rect;
0045         QString text;
0046         emit queryToolTip(helpEvent->pos(), rect, text);
0047 
0048         if (rect.isValid() && !text.isEmpty()) {
0049             auto parentWidget = static_cast<QWidget *>(parent());
0050             text = truncateLines(text, QToolTip::font(), helpEvent->globalPos(), qApp->desktop()->availableGeometry(parentWidget));
0051             QToolTip::showText(helpEvent->globalPos(), text, parentWidget, rect);
0052         }
0053 
0054         return true;
0055     }
0056 
0057     return QObject::eventFilter(watched, event);
0058 }
0059 
0060 // Primitive routine to truncate the text. size.width() is ignored, only
0061 // size.height() is used at the moment to keep it fast. It doesn't work
0062 // correct if text lines have different heights.
0063 QString truncateLines(const QString &text, const QFontMetrics &fm, const QSize &size)
0064 {
0065     const QChar newLine('\n');
0066 
0067     const int lineSpacing(fm.lineSpacing());
0068     const int numberOfLines(text.count(newLine) + 1);
0069     const int maxNumberOfLines(size.height() / lineSpacing);
0070 
0071     if (numberOfLines <= maxNumberOfLines)
0072         return text;
0073 
0074     const QChar *unicode(text.unicode());
0075     for (int count(maxNumberOfLines); count; ++unicode)
0076         if (*unicode == newLine)
0077             --count;
0078 
0079     return text.left(unicode - text.unicode() - 1);
0080 }
0081 
0082 // Truncate the tooltip's text if necessary
0083 QString truncateLines(const QString &text, const QFont &font, const QPoint &globalPos, const QRect &desktopGeometry)
0084 {
0085     // maximum size of the tooltip, - 10 just to be safe
0086     const int maxWidth(qMax(desktopGeometry.width() - globalPos.x(), globalPos.x()) - desktopGeometry.left() - 10);
0087     const int maxHeight(qMax(desktopGeometry.height() - globalPos.y(), globalPos.y()) - desktopGeometry.top() - 10);
0088 
0089     // calculate the tooltip's size
0090     QTextDocument layoutedText;
0091     layoutedText.setHtml(text);
0092     layoutedText.setDefaultFont(font);
0093 
0094     // only if the tooltip's size is bigger in x- and y-direction the text must
0095     // be truncated otherwise the tip is moved to a position where it fits
0096     return ((layoutedText.size().width() > maxWidth) && (layoutedText.size().height() > maxHeight))
0097         ? truncateLines(text, QFontMetrics(font), QSize(maxWidth, maxHeight))
0098         : text;
0099 }
0100 
0101 } // namespace Cervisia