Few fixes to PageViewMessage

- support for multiline/long messages (properly wrapped)
- react (resize) on parent resize
- code refactoring (common code in private methods)

REVIEW: 115596
remotes/origin/KDE/4.13
Luigi Toscano 12 years ago
parent ecf1f28290
commit 480df58d68
  1. 129
      ui/pageviewutils.cpp
  2. 3
      ui/pageviewutils.h

@ -231,6 +231,7 @@ PageViewMessage::PageViewMessage( QWidget * parent )
void PageViewMessage::display( const QString & message, const QString & details, Icon icon, int durationMs )
// give Caesar what belongs to Caesar: code taken from Amarok's osd.h/.cpp
// "redde (reddite, pl.) cesari quae sunt cesaris", just btw. :)
// The code has been heavily modified since then.
{
if ( !Okular::Settings::showOSD() )
{
@ -244,28 +245,7 @@ void PageViewMessage::display( const QString & message, const QString & details,
// reset vars
m_lineSpacing = 0;
// determine text rectangle
QRect textRect = fontMetrics().boundingRect( m_message );
textRect.translate( -textRect.left(), -textRect.top() );
textRect.adjust( 0, 0, 2, 2 );
int width = textRect.width(),
height = textRect.height();
if ( !m_details.isEmpty() )
{
// determine details text rectangle
QRect detailsRect = fontMetrics().boundingRect( m_details );
detailsRect.translate( -detailsRect.left(), -detailsRect.top() );
detailsRect.adjust( 0, 0, 2, 2 );
width = qMax( width, detailsRect.width() );
height += detailsRect.height();
// plus add a ~60% line spacing
m_lineSpacing = static_cast< int >( fontMetrics().height() * 0.6 );
height += m_lineSpacing;
}
// load icon (if set) and update geometry
// load icon (if set)
m_symbol = QPixmap();
if ( icon != None )
{
@ -288,18 +268,9 @@ void PageViewMessage::display( const QString & message, const QString & details,
break;
}
width += 2 + m_symbol.width();
height = qMax( height, m_symbol.height() );
}
// resize widget
resize( QRect( 0, 0, width + 10, height + 8 ).size() );
// if the layout is RtL, we can move it to the right place only after we
// know how much size it will take
if ( layoutDirection() == Qt::RightToLeft )
move( parentWidget()->width() - geometry().width() - 10 - 1, 10 );
computeSizeAndResize();
// show widget and schedule a repaint
show();
update();
@ -316,24 +287,94 @@ void PageViewMessage::display( const QString & message, const QString & details,
m_timer->start( durationMs );
} else if ( m_timer )
m_timer->stop();
qobject_cast<QAbstractScrollArea*>(parentWidget())->viewport()->installEventFilter(this);
}
void PageViewMessage::paintEvent( QPaintEvent * /* e */ )
QRect PageViewMessage::computeTextRect( const QString & message, int extra_width ) const
// Return the QRect which embeds the text
{
QRect textRect = fontMetrics().boundingRect( m_message );
int charSize = fontMetrics().averageCharWidth();
/* width of the viewport, minus 20 (~ size removed by further resizing),
minus the extra size (usually the icon width), minus (a bit empirical)
twice the mean width of a character to ensure that the bounding box is
really smaller than the container.
*/
const int boundingWidth = qobject_cast<QAbstractScrollArea*>(parentWidget())->viewport()->width() - 20 - ( extra_width > 0 ? 2 + extra_width : 0 ) - 2*charSize;
QRect textRect = fontMetrics().boundingRect( 0, 0, boundingWidth, 0,
Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, message );
textRect.translate( -textRect.left(), -textRect.top() );
textRect.adjust( 0, 0, 2, 2 );
return textRect;
}
void PageViewMessage::computeSizeAndResize()
{
// determine text rectangle
const QRect textRect = computeTextRect( m_message, m_symbol.width() );
int width = textRect.width(),
height = textRect.height();
if ( !m_details.isEmpty() )
{
// determine details text rectangle
const QRect detailsRect = computeTextRect( m_details, m_symbol.width() );
width = qMax( width, detailsRect.width() );
height += detailsRect.height();
// plus add a ~60% line spacing
m_lineSpacing = static_cast< int >( fontMetrics().height() * 0.6 );
height += m_lineSpacing;
}
// update geometry with icon information
if ( ! m_symbol.isNull() )
{
width += 2 + m_symbol.width();
height = qMax( height, m_symbol.height() );
}
// resize widget
resize( QRect( 0, 0, width + 10, height + 8 ).size() );
// if the layout is RtL, we can move it to the right place only after we
// know how much size it will take
if ( layoutDirection() == Qt::RightToLeft )
move( parentWidget()->width() - geometry().width() - 10 - 1, 10 );
}
bool PageViewMessage::eventFilter(QObject * obj, QEvent * event )
{
/* if the parent object (scroll area) resizes, the message should
resize as well */
if (event->type() == QEvent::Resize)
{
QResizeEvent *resizeEvent = static_cast<QResizeEvent *>(event);
if ( resizeEvent->oldSize() != resizeEvent->size() )
{
computeSizeAndResize();
}
}
// standard event processing
return QObject::eventFilter(obj, event);
}
void PageViewMessage::paintEvent( QPaintEvent * /* e */ )
{
const QRect textRect = computeTextRect( m_message, m_symbol.width() );
QRect detailsRect;
if ( !m_details.isEmpty() )
{
detailsRect = fontMetrics().boundingRect( m_details );
detailsRect.translate( -detailsRect.left(), -detailsRect.top() );
detailsRect.adjust( 0, 0, 2, 2 );
detailsRect = computeTextRect( m_details, m_symbol.width() );
}
int textXOffset = 0,
textYOffset = geometry().height() - textRect.height() / 2 - detailsRect.height() - m_lineSpacing,
// add 2 to account for the reduced drawRoundRect later
textYOffset = ( geometry().height() - textRect.height() - detailsRect.height() - m_lineSpacing + 2 ) / 2,
iconXOffset = 0,
iconYOffset = !m_symbol.isNull() ? ( geometry().height() - m_symbol.height() ) / 2 : 0,
shadowOffset = 1;
@ -355,15 +396,19 @@ void PageViewMessage::paintEvent( QPaintEvent * /* e */ )
if ( !m_symbol.isNull() )
painter.drawPixmap( 5 + iconXOffset, iconYOffset, m_symbol, 0, 0, m_symbol.width(), m_symbol.height() );
const int xStartPoint = 5 + textXOffset;
const int yStartPoint = textYOffset;
const int textDrawingFlags = Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap;
// draw shadow and text
painter.setPen( palette().color( QPalette::Window ).dark( 115 ) );
painter.drawText( 5 + textXOffset + shadowOffset, textYOffset + shadowOffset, m_message );
painter.drawText( xStartPoint + shadowOffset, yStartPoint + shadowOffset, textRect.width(), textRect.height(), textDrawingFlags, m_message );
if ( !m_details.isEmpty() )
painter.drawText( 5 + textXOffset + shadowOffset, textYOffset + textRect.height() + m_lineSpacing + shadowOffset, m_details );
painter.drawText( xStartPoint + shadowOffset, yStartPoint + textRect.height() + m_lineSpacing + shadowOffset, textRect.width(), detailsRect.height(), textDrawingFlags, m_details );
painter.setPen( palette().color( QPalette::WindowText ) );
painter.drawText( 5 + textXOffset, textYOffset, m_message );
painter.drawText( xStartPoint, yStartPoint, textRect.width(), textRect.height(), textDrawingFlags, m_message );
if ( !m_details.isEmpty() )
painter.drawText( 5 + textXOffset + shadowOffset, textYOffset + textRect.height() + m_lineSpacing, m_details );
painter.drawText( xStartPoint + shadowOffset, yStartPoint + textRect.height() + m_lineSpacing, textRect.width(), detailsRect.height(), textDrawingFlags, m_details );
}
void PageViewMessage::mousePressEvent( QMouseEvent * /*e*/ )

@ -108,10 +108,13 @@ class PageViewMessage : public QWidget
void display( const QString & message, const QString & details = QString(), Icon icon = Info, int durationMs = 4000 );
protected:
bool eventFilter(QObject * obj, QEvent * event );
void paintEvent( QPaintEvent * e );
void mousePressEvent( QMouseEvent * e );
private:
QRect computeTextRect( const QString & message, int extra_width ) const;
void computeSizeAndResize();
QString m_message;
QString m_details;
QPixmap m_symbol;

Loading…
Cancel
Save