Show tooltips for long entries of your custom model: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
(clean-up)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:HowTo]]<br />[[Category:snippets]]
[[Category:HowTo]]
[[Category:snippets]]


This tutorial shows how to display tool tips for long entries of your custom model. The &quot;long entries&amp;quot; in this case is a text that is truncated by the view.
This tutorial shows how to display tool tips for long entries of your custom model. The "long entries" in this case is a text that is truncated by the view.


This Wiki page based upon tutorial project &quot;1_readonly&amp;quot; found in Qt SDK. Use it to get similar output and to play with the code.
This Wiki page based upon tutorial project "1_readonly" found in Qt SDK. Use it to get similar output and to play with the code.


= Model =
= Model =
Line 9: Line 10:
In order to provide tool tips one need to handle Qt::ToolTipRole request in a model data method. This model returns the same text for both display and tool tip roles.
In order to provide tool tips one need to handle Qt::ToolTipRole request in a model data method. This model returns the same text for both display and tool tip roles.


<code>QVariant MyModel::data(const QModelIndex &amp;index, int role) const<br />{<br /> int row = index.row();<br /> int col = index.column();
<code>QVariant MyModel::data(const QModelIndex &index, int role) const
{
int row = index.row();
int col = index.column();


if (role  Qt::DisplayRole || role  Qt::ToolTipRole)<br /> {<br /> if (row  1 &amp;amp;&amp;amp; col  1)<br /> {<br /> return QString(&quot;Qt is a cross-platform application framework that is widely used for developing application software with a graphical user interface&amp;quot;);<br /> }<br /> else<br /> {<br /> return QString(&quot;Row%1, Column%2&amp;quot;)<br /> .arg(row + 1)<br /> .arg(col +1);<br /> }<br /> }<br /> return QVariant();<br />}</code>
if (role  Qt::DisplayRole || role  Qt::ToolTipRole)
{
if (row  1 && col  1)
{
return QString("Qt is a cross-platform application framework that is \
widely used for developing application software with a graphical user interface");
}
else
{
return QString("Row%1, Column%2")
.arg(row + 1)
.arg(col +1);
}
}
return QVariant();
}</code>


If we run the application then tool tips will appear for ''every'' item. Based on the specifications the desired behaviour might be different.
If we run the application then tool tips will appear for ''every'' item. Based on the specifications the desired behaviour might be different.
Line 17: Line 36:
= Event filter, class QToolTipper =
= Event filter, class QToolTipper =


To improve the situation we apply an event filter to the view. The QToolTipper class finds the correspondence between cursor position and model data. Then it gets the text for the tool tip. The text is checked to be inside a visual rectangle. If it is not, then the tool tip is shown.<br /><code>#ifndef QTOOLTIPPER_H_<br />#define QTOOLTIPPER_H_
To improve the situation we apply an event filter to the view. The QToolTipper class finds the correspondence between cursor position and model data. Then it gets the text for the tool tip. The text is checked to be inside a visual rectangle. If it is not, then the tool tip is shown.
<code>#ifndef QTOOLTIPPER_H_
#define QTOOLTIPPER_H_


#include &lt;QObject&amp;gt;<br />#include &lt;QAbstractItemView&amp;gt;<br />#include &lt;QHelpEvent&amp;gt;<br />#include &lt;QToolTip&amp;gt;
#include <QObject>
#include <QAbstractItemView>
#include <QHelpEvent>
#include <QToolTip>


class QToolTipper : public QObject<br />{<br /> Q_OBJECT<br />public:<br /> explicit QToolTipper(QObject* parent = NULL)<br /> : QObject(parent)<br /> {<br /> }
class QToolTipper : public QObject
{
Q_OBJECT
public:
explicit QToolTipper(QObject* parent = NULL)
: QObject(parent)
{
}


protected:<br /> bool eventFilter(QObject* obj, QEvent* event)<br /> {<br /> if (event-&gt;type() == QEvent::ToolTip)<br /> {<br /> QAbstractItemView* view = qobject_cast&amp;lt;QAbstractItemView*&gt;(obj-&gt;parent());<br /> if (!view)<br /> {<br /> return false;<br /> }
protected:
bool eventFilter(QObject* obj, QEvent* event)
{
if (event->type() == QEvent::ToolTip)
{
QAbstractItemView* view = qobject_cast<QAbstractItemView*>(obj->parent());
if (!view)
{
return false;
}


QHelpEvent* helpEvent = static_cast&amp;lt;QHelpEvent*&gt;(event);<br /> QPoint pos = helpEvent-&gt;pos();<br /> QModelIndex index = view-&gt;indexAt(pos);<br /> if (!index.isValid())<br /> return false;
QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
QPoint pos = helpEvent->pos();
QModelIndex index = view->indexAt(pos);
if (!index.isValid())
return false;


QString itemText = view-&gt;model()<s>&gt;data(index).toString();<br /> QString itemTooltip = view</s>&gt;model()<s>&gt;data(index, Qt::ToolTipRole).toString();
QString itemText = view->model()->data(index).toString();
<br /> QFontMetrics fm(view</s>&gt;font());<br /> int itemTextWidth = fm.width(itemText);<br /> QRect rect = view-&gt;visualRect(index);<br /> int rectWidth = rect.width();
QString itemTooltip = view->model()->data(index, Qt::ToolTipRole).toString();


if ((itemTextWidth &gt; rectWidth) &amp;&amp; !itemTooltip.isEmpty())<br /> {<br /> QToolTip::showText(helpEvent-&gt;globalPos(), itemTooltip, view, rect);<br /> }<br /> else<br /> {<br /> QToolTip::hideText();<br /> }<br /> return true;<br /> }<br /> return false;<br /> }<br />};
QFontMetrics fm(view->font());
int itemTextWidth = fm.width(itemText);
QRect rect = view->visualRect(index);
int rectWidth = rect.width();
 
if ((itemTextWidth > rectWidth) && !itemTooltip.isEmpty())
{
QToolTip::showText(helpEvent->globalPos(), itemTooltip, view, rect);
}
else
{
QToolTip::hideText();
}
return true;
}
return false;
}
};


#endif</code>
#endif</code>
Line 38: Line 99:
It is the viewport that receives necessary events. So the event filter is attached to the viewport.
It is the viewport that receives necessary events. So the event filter is attached to the viewport.


<code>tableView.setModel( &amp;myModel );<br />tableView.viewport()-&gt;installEventFilter(new QToolTipper(&amp;tableView));<br />tableView.show();</code>
<code>tableView.setModel( &myModel );
tableView.viewport()->installEventFilter(new QToolTipper(&tableView));
tableView.show();</code>


=== Output ===
=== Output ===


Upper picture demonstrates the tool tip and the lower picture demonstrates no tool tip for short text.
Upper picture demonstrates the tool tip and the lower picture demonstrates no tool tip for short text.

Latest revision as of 14:46, 24 March 2016


This tutorial shows how to display tool tips for long entries of your custom model. The "long entries" in this case is a text that is truncated by the view.

This Wiki page based upon tutorial project "1_readonly" found in Qt SDK. Use it to get similar output and to play with the code.

Model

In order to provide tool tips one need to handle Qt::ToolTipRole request in a model data method. This model returns the same text for both display and tool tip roles.

QVariant MyModel::data(const QModelIndex &index, int role) const
{
 int row = index.row();
 int col = index.column();

if (role  Qt::DisplayRole || role  Qt::ToolTipRole)
 {
 if (row  1 && col  1)
 {
 return QString("Qt is a cross-platform application framework that is \
widely used for developing application software with a graphical user interface");
 }
 else
 {
 return QString("Row%1, Column%2")
 .arg(row + 1)
 .arg(col +1);
 }
 }
 return QVariant();
}

If we run the application then tool tips will appear for every item. Based on the specifications the desired behaviour might be different.

Event filter, class QToolTipper

To improve the situation we apply an event filter to the view. The QToolTipper class finds the correspondence between cursor position and model data. Then it gets the text for the tool tip. The text is checked to be inside a visual rectangle. If it is not, then the tool tip is shown.

#ifndef QTOOLTIPPER_H_
#define QTOOLTIPPER_H_

#include <QObject>
#include <QAbstractItemView>
#include <QHelpEvent>
#include <QToolTip>

class QToolTipper : public QObject
{
 Q_OBJECT
public:
 explicit QToolTipper(QObject* parent = NULL)
 : QObject(parent)
 {
 }

protected:
 bool eventFilter(QObject* obj, QEvent* event)
 {
 if (event->type() == QEvent::ToolTip)
 {
 QAbstractItemView* view = qobject_cast<QAbstractItemView*>(obj->parent());
 if (!view)
 {
 return false;
 }

QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
 QPoint pos = helpEvent->pos();
 QModelIndex index = view->indexAt(pos);
 if (!index.isValid())
 return false;

QString itemText = view->model()->data(index).toString();
 QString itemTooltip = view->model()->data(index, Qt::ToolTipRole).toString();

 QFontMetrics fm(view->font());
 int itemTextWidth = fm.width(itemText);
 QRect rect = view->visualRect(index);
 int rectWidth = rect.width();

if ((itemTextWidth > rectWidth) && !itemTooltip.isEmpty())
 {
 QToolTip::showText(helpEvent->globalPos(), itemTooltip, view, rect);
 }
 else
 {
 QToolTip::hideText();
 }
 return true;
 }
 return false;
 }
};

#endif

Installtion of the event filter

It is the viewport that receives necessary events. So the event filter is attached to the viewport.

tableView.setModel( &myModel );
tableView.viewport()->installEventFilter(new QToolTipper(&tableView));
tableView.show();

Output

Upper picture demonstrates the tool tip and the lower picture demonstrates no tool tip for short text.