/****************************************************************************
** MODIFIED FOR USAGE IN KOCTAVE BY MATIAS HENTTUNEN 2002
**
** Original file is from QT - demos.
** This file is part of an example program for Qt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#include "dirview.h"
#include "icons.h"		//should be loaded not included in a header..

#include <qdir.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qpixmap.h>
#include <qevent.h>
#include <qpoint.h>
#include <qmessagebox.h>
#include <qdragobject.h>
#include <qmime.h>
#include <qstrlist.h>
#include <qstringlist.h>
#include <qapplication.h>
#include <qheader.h>


QPixmap *folderLocked = 0;
QPixmap *folderClosed = 0;
QPixmap *folderOpen = 0;
QPixmap *fileNormal = 0;

/*****************************************************************************
 *
 * Class Directory
 *
 *****************************************************************************/

Directory::Directory( Directory * parent, const QString& filename )
: QListViewItem( parent ), f(filename), showDirsOnly( parent->showDirsOnly ),pix( 0 )
{
    //better way of doing this ?
    fileNormal = new QPixmap(pix_file);
    folderOpen = new QPixmap(folder_open_xpm);
    p = parent;

    readable = QDir( fullName() ).isReadable();
    if ( !readable )
    {
	folderLocked=new QPixmap(folder_locked);
	setPixmap( folderLocked );
    }
    else
    {
        folderClosed=new QPixmap(folder_closed_xpm);
	setPixmap( folderClosed );

    }
}


Directory::Directory( QListView * parent, const QString& filename )
: QListViewItem( parent ), f(filename),showDirsOnly( ( (DirectoryView*)parent )->showDirsOnly() ),pix( 0 )
{
    p = 0;
    readable = QDir( fullName() ).isReadable();
}


void Directory::setPixmap( QPixmap *px )
{
    pix = px;
    setup();
    widthChanged( 0 );
    invalidateHeight();
    repaint();
}


const QPixmap *Directory::pixmap( int i ) const
{
    if ( i )return 0;
    return pix;
}

void Directory::setOpen( bool o )
{
    if ( o )
	setPixmap( folderOpen );
    else
	setPixmap( folderClosed );

    if ( o && !childCount() ) {
	QString s( fullName() );
	QDir thisDir( s );
	if ( !thisDir.isReadable() ) {
	    readable = FALSE;
	    setExpandable( FALSE );
	    return;
	}

	listView()->setUpdatesEnabled( FALSE );
	const QFileInfoList * files = thisDir.entryInfoList();
	if ( files ) {
	    QFileInfoListIterator it( *files );
	    QFileInfo * fi;
	    while( (fi=it.current()) != 0 ) 
	    {
		++it;
		if ( fi->fileName() == "." || fi->fileName() == ".." )
		    ; // nothing
		else if ( fi->isSymLink() && !showDirsOnly ) 
		{
		    FileItem *item = new FileItem( this, fi->fileName(), "Symbolic Link" );
		    item->setPixmap( folderClosed);		//fileNormal );
		}
		else if ( fi->isDir() )
		    (void)new Directory( this, fi->fileName() );
		else if ( !showDirsOnly ) 
		{
		    FileItem *item = new FileItem( this, fi->fileName(), fi->isFile()?"File":"Special" );
		    item->setPixmap( fileNormal );
		}
	    }
	}
	listView()->setUpdatesEnabled( TRUE );
    }
    QListViewItem::setOpen( o );
}


void Directory::setup()
{
    setExpandable( TRUE );
    QListViewItem::setup();
}


QString Directory::fullName()
{
    QString s;
    if ( p ) 
    {
	s = p->fullName();
	s.append( f.name() );
	s.append( "/" );
    } else {
	s = f.name();
    }
    return s;
}


QString Directory::text( int column ) const
{
    if ( column == 0 )
	return f.name();
    else if ( readable )
	return "Directory";
    else
	return "Unreadable Directory";
}

/*****************************************************************************
 *
 * Class DirectoryView
 *
 *****************************************************************************/
DirectoryView::DirectoryView( QWidget *parent, const char *name, bool sdo )
: QListView( parent, name ), dirsOnly( sdo ), oldCurrent( 0 ), dropItem( 0 ), mousePressed( FALSE )
{
    addColumn( "Name" );
    setTreeStepSize( 20 );
    const QFileInfoList* roots = QDir::drives();
    QPtrListIterator<QFileInfo> i(*roots);
    QFileInfo* fi;
    while( (fi = *i) )
    {
        ++i;
        Directory * root = new Directory( this, fi->filePath() );
        if ( roots->count() <= 1 ) root->setOpen( true );       // be interesting
    }
    setDir( QDir::homeDirPath() );          			//goto home dir by default

    autoopen_timer = new QTimer( this );
    if ( !folderLocked ) 
    {
	folderLocked = new QPixmap( folder_locked );
	folderClosed = new QPixmap( folder_closed_xpm );
	folderOpen = new QPixmap( folder_open_xpm );
	fileNormal = new QPixmap( pix_file );
    }

    connect( this, SIGNAL( doubleClicked( QListViewItem * ) ),
	     this, SLOT( slotClicked( QListViewItem * ) ) );

    connect( this, SIGNAL( returnPressed( QListViewItem * ) ),
	     this, SLOT( slotClicked( QListViewItem * ) ) );

    setAcceptDrops( TRUE );
    viewport()->setAcceptDrops( FALSE );
    connect( autoopen_timer, SIGNAL( timeout() ),this, SLOT( openFolder() ) );
}


// it it is a valid file open it..
void DirectoryView::slotClicked( QListViewItem *i )
{
	    QString source = fullPath(i);
	    if ( QFile::exists(source) )
	    {
		QFileInfo f=QFileInfo(source);
		if(f.isFile() )			//this is a file!
		{	//only open "valid files", could be extended to images, wave etc ?
		    if(f.extension() == "m" || f.extension() ==".oct" || f.extension() =="txt")
		    emit openFile( source );
		    
		    //qDebug("click");		//send url!
		}
	    }
	    else
	    {
	        if ( !i || !showDirsOnly() )return;
		Directory *dir = (Directory*)i;
		emit folderSelected( dir->fullName() );
	    }	
}

void DirectoryView::openFolder()
{
    autoopen_timer->stop();
    if ( dropItem && !dropItem->isOpen() ) 
    {
	dropItem->setOpen( TRUE );
	dropItem->repaint();
    }
}

static const int autoopenTime = 750;

QString DirectoryView::fullPath(QListViewItem* item)
{
    QString fullpath = item->text(0);
    while ( (item=item->parent()) ) {
	if ( item->parent() )
	    fullpath = item->text(0) + "/" + fullpath;
	else
	    fullpath = item->text(0) + fullpath;
    }
    return fullpath;
}

// register click
void DirectoryView::contentsDoubleClickEvent( QMouseEvent *e)
{
    qDebug("dblclick");

}

//paint the rectangle around a item in the listbox
void DirectoryView::contentsMousePressEvent( QMouseEvent* e )
{
    QListView::contentsMousePressEvent(e);
    QPoint p( contentsToViewport( e->pos() ) );
    QListViewItem *i = itemAt( p );
    if ( i ) 
    {
	// if the user clicked into the root decoration of the item, don't try to start a drag!
	if ( p.x() > header()->cellPos( header()->mapToActual( 0 ) ) +
	     treeStepSize() * ( i->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ||
	     p.x() < header()->cellPos( header()->mapToActual( 0 ) ) ){
	    presspos = e->pos();
	    mousePressed = TRUE;
	}
    }

}

void DirectoryView::contentsMouseReleaseEvent( QMouseEvent * )
{
    mousePressed = FALSE;
}

void DirectoryView::setDir( const QString &s )
{
    QListViewItemIterator it( this );
    ++it;
    for ( ; it.current(); ++it ) {
	it.current()->setOpen( FALSE );
    }

    QStringList lst( QStringList::split( "/", s ) );
    QListViewItem *item = firstChild();
    QStringList::Iterator it2 = lst.begin();
    for ( ; it2 != lst.end(); ++it2 ) {
	while ( item ) {
	    if ( item->text( 0 ) == *it2 ) {
		item->setOpen( TRUE );
		break;
	    }
	    item = item->itemBelow();
	}
    }

    if ( item )
	setCurrentItem( item );
}

void FileItem::setPixmap( QPixmap *p )
{
    pix = p;
    setup();
    widthChanged( 0 );
    invalidateHeight();
    repaint();
}


const QPixmap *FileItem::pixmap( int i ) const
{
    if ( i )
	return 0;
    return pix;
}


syntax highlighted by Code2HTML, v. 0.9.1