/***************************************************************************
     gradientelidelabel.cpp -  adds a gradient-like elide to long labels
                             -------------------
    begin                : Thursday May 14 2009
    copyright            : (C) 2009 by Adam Goossens
    email                : fontknocker@gmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "gradientelidelabel.h"

#include <QApplication>
#include <QPainter>
#include <QFontMetrics>
#include <QLinearGradient>
#include <QRegExp>

#include "utils/kmessshared.h"

GradientElideLabel::GradientElideLabel( QWidget *parent )
  : QLabel(parent)
{
}

GradientElideLabel::GradientElideLabel( const QString &text, QWidget *parent )
  : QLabel( text, parent)
{
  setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed) );
  setText(text);
}

GradientElideLabel::~GradientElideLabel()
{
}

void GradientElideLabel::setText( const QString &text )
{
  QLabel::setText( text );
  cleanText = text;

  // strip out any HTML tags and replace HTML entities.
  // at this point "cleanText" should *roughly* resemble the
  // actual formatted string in width (excusing bold face and what not).
  cleanText.replace(QRegExp("</?\\w+\\s*[^>]*>"), "");
  cleanText = KMessShared::htmlUnescape(cleanText);
}

void GradientElideLabel::paintEvent(QPaintEvent *event)
{
  QFontMetrics fm(font());
  if (fm.width(cleanText) <= contentsRect().width())
  {
    QLabel::paintEvent(event);
    return;
  }

  // if we get here we believe that the text will be too long for the label
  // so apply the fade.

  // first, create a pixmap and have QLabel paint itself onto it.
  // this handles the display of rich text.
  QPixmap label = QPixmap(width(), height());
  label.fill(Qt::transparent);

  // force the label to draw itself to the pixmap.
  // we'll then fade out the pixmap and draw it where it should really go.
  QPainter::setRedirected(this, &label);

  QLabel::paintEvent(event);

  QPainter::restoreRedirected(this);

  // create a painter to paint on the pixmap.
  QPainter p(&label);
  p.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing, true );

  // create a linear gradient, white to transparent.
  QLinearGradient gradient(contentsRect().topLeft(), contentsRect().topRight());

  if( QApplication::isLeftToRight() )
  {
    gradient.setColorAt( 0.75, Qt::white );
    gradient.setColorAt( 1.00, Qt::transparent );
  }
  else
  {
    gradient.setColorAt( 0.25, Qt::white );
    gradient.setColorAt( 0.00, Qt::transparent );
  }

  // now composite the gradient and the pixmap.
  p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
  p.fillRect(rect(), QBrush(gradient));

  // now paint that pixmap onto ourselves.
  QPainter pUs(this);
  pUs.drawPixmap(rect(), label);
}

