//GPL'd with permission to link against QT of any license.
//Kevin Smith 2003
//qpen outline?

#include <qapplication.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qtimer.h>
#include <qvbox.h>
#include <qpixmap.h>
#include <qtooltip.h>
#include <qpointarray.h>

#include "qpassivepopup.h"

static const int DEFAULT_POPUP_TIME = 6*1000;
static const int POPUP_FLAGS = Qt::WStyle_Customize | Qt::WDestructiveClose | Qt::WX11BypassWM
                             | Qt::WStyle_StaysOnTop | Qt::WStyle_Tool | Qt::WStyle_NoBorder;


QPassivePopup::QPassivePopup( QWidget *parent, const char *name, WFlags f )
    : QFrame( 0, name, f | POPUP_FLAGS ),
      window( parent ? parent->winId() : 0L ), msgView( 0 ), layout( 0 ),
      hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ), m_autoDelete( false ), d( 0 )
{
    init();
}

QPassivePopup::QPassivePopup( const char *name, WFlags f )
    : QFrame( 0, name, f | POPUP_FLAGS ),
      window( 0 ), msgView( 0 ), layout( 0 ),
      hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ), m_autoDelete( false ), d( 0 )
{
    init();
}

QPassivePopup::QPassivePopup( WId win, const char *name, WFlags f )
    : QFrame( 0, name, f | POPUP_FLAGS ),
      window( win ), msgView( 0 ), layout( 0 ),
      hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ), m_autoDelete( false ), d( 0 )
{
    init();
}

void QPassivePopup::init()
{
    setFrameStyle( QFrame::Box| QFrame::Plain );
    setLineWidth( 2 );
    connect( hideTimer, SIGNAL( timeout() ), SLOT( hide() ) );
    connect( this, SIGNAL( clicked() ), SLOT( hide() ) );
}

QPassivePopup::~QPassivePopup()
{
}

void QPassivePopup::setView( QWidget *child )
{
    delete msgView;
    msgView = child;
    
    delete layout;
    //layout = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );//KEVIN

    this->setFrameStyle(PopupPanel);
    this->setFrameShadow(Raised);
    this->setLineWidth(3);
    this->setPalette(QToolTip::palette());
    this->setAutoMask(true);
    
    layout = new QVBoxLayout( this );//KEVIN
    layout->addWidget( msgView );
    layout->activate();
}

void QPassivePopup::setView( const QString &caption, const QString &text,
                             const QPixmap &icon )
{
    QVBox *vb = new QVBox( this );
    //vb->setSpacing( KDialog::spacingHint() ); //KEVIN
    vb->setSpacing(5);//KEVIN
    QHBox *hb=0;
    if ( !icon.isNull() ) {
	hb = new QHBox( vb );
	//hb->setMargin( KDialog::marginHint() );//KEVIN
	//hb->setSpacing( KDialog::spacingHint() );//KEVIN
        hb->setMargin( 5 );//KEVIN
	hb->setSpacing( 5 );//KEVIN
	ttlIcon = new QLabel( hb, "title_icon" );
	ttlIcon->setPixmap( icon );
    }

    if ( !caption.isNull() ) {
	ttl = new QLabel( caption, hb ? hb : vb, "title_label" );
	QFont fnt = ttl->font();
	fnt.setBold( true );
	ttl->setFont( fnt );
	ttl->setAlignment( Qt::AlignHCenter );
    }

    //KEVIN thinks that text should be centred by default.
    msg = new QLabel( text, vb, "msg_label" );
    msg->setAlignment(Qt::AlignHCenter);
    setView( vb );
}

void QPassivePopup::setView( const QString &caption, const QString &text )
{
    setView( caption, text, QPixmap() );
}

void QPassivePopup::setTimeout( int delay )
{
    hideDelay = delay;
	if( hideTimer->isActive() )
		hideTimer->changeInterval( delay );
}

void QPassivePopup::setAutoDelete( bool autoDelete )
{
    m_autoDelete = autoDelete;
}

void QPassivePopup::mouseReleaseEvent( QMouseEvent *e )
{
    emit clicked();
    emit clicked( e->pos() );
}

//
// Main Implementation
//

void QPassivePopup::show()
{
    if ( size() != sizeHint() )
	resize( sizeHint() );

    positionSelf();
    QFrame::show();

    int delay = hideDelay;
    if ( delay < 0 )
	delay = DEFAULT_POPUP_TIME;

    if ( delay > 0 ) {
	hideTimer->start( delay );
    }
}

void QPassivePopup::hideEvent( QHideEvent * )
{
    hideTimer->stop();
    if ( m_autoDelete )
        deleteLater();
}

void QPassivePopup::positionSelf()
{
    //This is all KDE-specifix stuff, I've had to comment out (KEVIN)
    /*
    NETWinInfo ni( qt_xdisplay(), window, qt_xrootwin(),
		   NET::WMIconGeometry | NET::WMKDESystemTrayWinFor );

    // Figure out where to put the popup. Note that we must handle
    // windows that skip the taskbar cleanly
    QRect target;
    if ( ni.kdeSystemTrayWinFor() ) {
	NETRect frame, win;
	ni.kdeGeometry( frame, win );
	target.setRect( win.pos.x, win.pos.y, win.size.width, win.size.height );
    }
    else if ( ni.state() & NET::SkipTaskbar ) {
	target.setRect( 0, 0, 0, 0 );
    }
    else {
	NETRect r = ni.iconGeometry();
	target.setRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
    }
    */
    //KEVIN Hack added

    QRect target;
    target.setRect((qApp->desktop()->width()/20)*19,qApp->desktop()->height(),0,0);
    
    //</hack>
    moveNear( target );
}

void QPassivePopup::moveNear( QRect target )
{
    QPoint pos = target.topLeft();
    int x = pos.x();
    int y = pos.y();
    int w = width();
    int h = height();

    if ( x < ( qApp->desktop()->width() / 2 ) )
	x = x + target.width();
    else
	x = x - w;

    // It's apparently trying to go off screen, so display it ALL at the bottom.
    if ( (y + h) > qApp->desktop()->height() )
	y = qApp->desktop()->height() - h;

#ifdef OLD_BITS
    if ( (x - w) >= 0  )
	x = x - w;
#endif

    move( x, y );
}

//
// Convenience Methods
//

QPassivePopup *QPassivePopup::message( const QString &caption, const QString &text,
				       const QPixmap &icon,
				       QWidget *parent, const char *name, int timeout )
{
    QPassivePopup *pop = new QPassivePopup( parent, name );
    pop->setAutoDelete( true );
    pop->setView( caption, text, icon );
    pop->hideDelay = timeout;
    pop->show();

    return pop;
}

QPassivePopup *QPassivePopup::message( const QString &text, QWidget *parent, const char *name )
{
    return message( QString::null, text, QPixmap(), parent, name );
}

QPassivePopup *QPassivePopup::message( const QString &caption, const QString &text,
				       QWidget *parent, const char *name )
{
    return message( caption, text, QPixmap(), parent, name );
}

QPassivePopup *QPassivePopup::message( const QString &caption, const QString &text,
				       const QPixmap &icon, WId parent, const char *name, int timeout )
{
    QPassivePopup *pop = new QPassivePopup( parent, name );
    pop->setAutoDelete( true );

    pop->setView( caption, text, icon );
    pop->hideDelay = timeout;
    pop->show();
    return pop;
}

QString *QPassivePopup::splitMessage(QString caption, uint splitsize, uint maxsize){
    QString *splitcaption;
    printf("Splitting message of length %d with splitsize %d and maxsize %d \n", caption.length(), splitsize, maxsize);
    if (caption.length()>maxsize){
        splitcaption=new QString(caption.left(maxsize));}
    else{
        splitcaption=new QString(caption);}
    for (uint i=splitsize;i<caption.length();i+=splitsize){
        bool truncated=false;
        for (uint j=i-5;j<i+5;j++){
            if (splitcaption->at(j).isSpace()) {
                QString* old=splitcaption;
                printf("Split on char %c, number %d\n", splitcaption->at(j).latin1(),j);
                splitcaption=new QString(splitcaption->left(j)+"\n"+splitcaption->right(splitcaption->length()-j));
                truncated=true;
                delete old;
                i=j;
                break;
            }
        }
        if (!truncated){
            QString *old=splitcaption;
            printf("forced to split at %d\n",i);
            splitcaption=new QString(splitcaption->left(i)+"-\n "+splitcaption->right(splitcaption->length()-i));
            delete old;
        }
    }
    return splitcaption;
}

void QPassivePopup::updateMask()
{
        //QRegion mask(10, 10, width() - 20, height() - 20);
        QRegion mask(0, 0, width(), height());
	/*QPoint corners[8] = {
		QPoint(width() - 50, 10),
		QPoint(10, 10),
		QPoint(10, height() - 50),
		QPoint(width() - 50, height() - 50),
                QPoint(width() - 10, 10),
		QPoint(10, 10),
		QPoint(10, height() - 10),
		QPoint(width() - 10, height() - 10)
	};*/
        QPoint corners[8] = {
		QPoint(width()-40, 0),
		QPoint(0, 0),
		QPoint(0, height()-40),
		QPoint(width()-40, height()-40),
                QPoint(width(), 0),
		QPoint(0, 0),
		QPoint(0, height()),
		QPoint(width(), height())
	};
	for (int i = 0; i < 2; ++i)
	{
		QPointArray corner;
		corner.makeArc(corners[i].x(), corners[i].y(), 40, 40, i * 16 * 90, 16 * 90);
		corner.resize(corner.size() + 1);
		corner.setPoint(corner.size() - 1, corners[i + 4]);
		mask -= corner;
	}
	bool bottom, right;
	QDesktopWidget* tmp = QApplication::desktop();
	QRect deskRect;
	// get screen-geometry for screen our anchor is on
	// (geometry can differ from screen to screen!
	deskRect = tmp->screenGeometry( tmp->screenNumber(this->pos()) );
	bottom = this->pos().y() + height() > deskRect.height() - 48;
	right = this->pos().x() + width() > deskRect.width() - 48;

	/*QPointArray arrow(4);
	arrow.setPoint(0, QPoint(right ? width() : 0, bottom ? height() : 0));
	arrow.setPoint(1, QPoint(right ? width() - 10 : 10, bottom ? height() - 30 : 30));
	arrow.setPoint(2, QPoint(right ? width() - 30 : 30, bottom ? height() - 10 : 10));
	arrow.setPoint(3, arrow[0]);
	mask += arrow;*/
	setMask(mask);
	/*move(right ? this->pos().x() - width() : this->pos().x(),
          bottom ? this->pos().y() - height() : this->pos().y());*/
}

#include "qpassivepopup.moc"

