/* This file is part of the KDE projects
   Copyright (C) 2000 David Faure <faure@kde.org>

   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.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "konq_dirpart.h"
#include "konq_bgnddlg.h"
#include "konq_propsview.h"
#include "konq_settings.h"

#include <kio/paste.h>
#include <kapplication.h>
#include <kaction.h>
#include <kdatastream.h>
#include <kdebug.h>
#include <kdirlister.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <konq_drag.h>
#include <kparts/browserextension.h>
#include <kurldrag.h>
#include <kuserprofile.h>
#include <kurifilter.h>
#include <kglobalsettings.h>

#include <qapplication.h>
#include <qclipboard.h>
#include <qfile.h>
#include <qguardedptr.h>
#include <assert.h>
#include <qvaluevector.h>

class KonqDirPart::KonqDirPartPrivate
{
public:
    KonqDirPartPrivate() : dirLister( 0 ) {}
    QStringList mimeFilters;
    KToggleAction *aEnormousIcons;
    KToggleAction *aSmallMediumIcons;
    QValueVector<int> iconSize;
            
    KDirLister* dirLister;
    bool dirSizeDirty;

    void findAvailableIconSizes(void);
    int findNearestIconSize(int size);
    int nearestIconSizeError(int size);
};

void KonqDirPart::KonqDirPartPrivate::findAvailableIconSizes(void)
{
    KIconTheme *root = KGlobal::instance()->iconLoader()->theme();
    iconSize.resize(1);
    if (root) {
	QValueList<int> avSizes = root->querySizes(KIcon::Desktop);
        kdDebug(1203) << "The icon theme handles the sizes:" << avSizes << endl;
	qHeapSort(avSizes);
	int oldSize = -1;
	if (avSizes.count() < 10) {
	    // Fixed or threshold type icons
	    QValueListConstIterator<int> i;
	    for (i = avSizes.begin(); i != avSizes.end(); i++) {
		// Skip duplicated values (sanity check)
		if (*i != oldSize) iconSize.append(*i);
		oldSize = *i;
	    }
	} else {
	    // Scalable icons.
	    const int progression[] = {16, 22, 32, 48, 64, 96, 128, 192, 256};

	    QValueListConstIterator<int> j = avSizes.begin();
	    for (uint i = 0; i < 9; i++) {
		while (j++ != avSizes.end()) {
		    if (*j >= progression[i]) {
			iconSize.append(*j);
			kdDebug(1203) << "appending " << *j << " size." << endl;
			break;
		    }
		}
	    }
	}
    } else {
	iconSize.append(KIcon::SizeSmall); // 16
	iconSize.append(KIcon::SizeMedium); // 32
	iconSize.append(KIcon::SizeLarge); // 48
	iconSize.append(KIcon::SizeHuge); // 64
    }
    kdDebug(1203) << "Using " << iconSize.count() << " icon sizes." << endl;
}

int KonqDirPart::KonqDirPartPrivate::findNearestIconSize(int preferred)
{
    int s1 = iconSize[1];
    if (preferred == 0) return KGlobal::iconLoader()->currentSize(KIcon::Desktop);
    if (preferred <= s1) return s1;
    for (uint i = 2; i <= iconSize.count(); i++) {
        if (preferred <= iconSize[i]) {
	    if (preferred - s1 <  iconSize[i] - preferred) return s1;
	    else return iconSize[i];
	} else {
	    s1 = iconSize[i];
	}
    }
    return s1;
}

int KonqDirPart::KonqDirPartPrivate::nearestIconSizeError(int size)
{
    return QABS(size - findNearestIconSize(size));
}

KonqDirPart::KonqDirPart( QObject *parent, const char *name )
            :KParts::ReadOnlyPart( parent, name ),
    m_pProps( 0L ),
    m_findPart( 0L )
{
    d = new KonqDirPartPrivate;
    resetCount();
    //m_bMultipleItemsSelected = false;

    connect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(slotClipboardDataChanged()) );

    actionCollection()->setHighlightingEnabled( true );

    m_paIncIconSize = new KAction( i18n( "Enlarge Icons" ), "viewmag+", 0, this, SLOT( slotIncIconSize() ), actionCollection(), "incIconSize" );
    m_paDecIconSize = new KAction( i18n( "Shrink Icons" ), "viewmag-", 0, this, SLOT( slotDecIconSize() ), actionCollection(), "decIconSize" );

    m_paDefaultIcons = new KRadioAction( i18n( "&Default Size" ), 0, actionCollection(), "modedefault" );
    d->aEnormousIcons = new KRadioAction( i18n( "&Huge" ), 0,
	    actionCollection(), "modeenormous" );
    m_paHugeIcons = new KRadioAction( i18n( "&Very Large" ), 0, actionCollection(), "modehuge" );
    m_paLargeIcons = new KRadioAction( i18n( "&Large" ), 0, actionCollection(), "modelarge" );
    m_paMediumIcons = new KRadioAction( i18n( "&Medium" ), 0, actionCollection(), "modemedium" );
    d->aSmallMediumIcons = new KRadioAction( i18n( "&Small" ), 0,
	    actionCollection(), "modesmallmedium" );
    m_paSmallIcons = new KRadioAction( i18n( "&Tiny" ), 0, actionCollection(), "modesmall" );

    m_paDefaultIcons->setExclusiveGroup( "ViewMode" );
    d->aEnormousIcons->setExclusiveGroup( "ViewMode" );
    m_paHugeIcons->setExclusiveGroup( "ViewMode" );
    m_paLargeIcons->setExclusiveGroup( "ViewMode" );
    m_paMediumIcons->setExclusiveGroup( "ViewMode" );
    d->aSmallMediumIcons->setExclusiveGroup( "ViewMode" );
    m_paSmallIcons->setExclusiveGroup( "ViewMode" );

    connect( m_paDefaultIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
    connect( d->aEnormousIcons, SIGNAL( toggled( bool ) ),
	    this, SLOT( slotIconSizeToggled( bool ) ) );
    connect( m_paHugeIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
    connect( m_paLargeIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
    connect( m_paMediumIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
    connect( d->aSmallMediumIcons, SIGNAL( toggled( bool ) ),
	    this, SLOT( slotIconSizeToggled( bool ) ) );
    connect( m_paSmallIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );

    connect( kapp, SIGNAL(iconChanged(int)), SLOT(slotIconChanged(int)) );
#if 0
    // Extract 6 icon sizes from the icon theme.
    // Use 16,22,32,48,64,128 as default.
    // Use these also if the icon theme is scalable.
    int i;
    d->iconSize[0] = 0; // Default value
    d->iconSize[1] = KIcon::SizeSmall; // 16
    d->iconSize[2] = KIcon::SizeSmallMedium; // 22
    d->iconSize[3] = KIcon::SizeMedium; // 32
    d->iconSize[4] = KIcon::SizeLarge; // 48
    d->iconSize[5] = KIcon::SizeHuge; // 64
    d->iconSize[6] = KIcon::SizeEnormous; // 128
    d->iconSize[7] = 192;
    d->iconSize[8] = 256;
    KIconTheme *root = KGlobal::instance()->iconLoader()->theme();
    if (root)
    {
      QValueList<int> avSizes = root->querySizes(KIcon::Desktop);
      kdDebug(1203) << "the icon theme handles the following sizes:" << avSizes << endl;
      if (avSizes.count() < 10) {
	// Use the icon sizes supplied by the theme.
	// If avSizes contains more than 10 entries, assume a scalable
	// icon theme.
	QValueList<int>::Iterator it;
	for (i=1, it=avSizes.begin(); (it!=avSizes.end()) && (i<7); it++, i++)
	{
	  d->iconSize[i] = *it;
	  kdDebug(1203) << "m_iIconSize[" << i << "] = " << *it << endl;
	}
	// Generate missing sizes
	for (; i < 7; i++) {
	  d->iconSize[i] = d->iconSize[i - 1] + d->iconSize[i - 1] / 2 ;
	  kdDebug(1203) << "m_iIconSize[" << i << "] = " << d->iconSize[i] << endl;
	}
      }
    }
#else
    d->iconSize.reserve(10);
    d->iconSize.append(0); // Default value
    adjustIconSizes();
#endif

    // Remove in KDE4 ...
    // These are here in the event subclasses access them.
    m_iIconSize[1] = KIcon::SizeSmall;
    m_iIconSize[2] = KIcon::SizeMedium;
    m_iIconSize[3] = KIcon::SizeLarge;
    m_iIconSize[4] = KIcon::SizeHuge;
    // ... up to here

    KAction *a = new KAction( i18n( "Configure Background..." ), "background", 0, this, SLOT( slotBackgroundSettings() ),
                              actionCollection(), "bgsettings" );

    a->setToolTip( i18n( "Allows choosing of background settings for this view" ) );
}

KonqDirPart::~KonqDirPart()
{
    // Close the find part with us
    delete m_findPart;
    delete d;
    d = 0;
}

void KonqDirPart::adjustIconSizes()
{
    d->findAvailableIconSizes();
    m_paSmallIcons->setEnabled(d->findNearestIconSize(16) < 20);
    d->aSmallMediumIcons->setEnabled(d->nearestIconSizeError(22) < 2);
    m_paMediumIcons->setEnabled(d->nearestIconSizeError(32) < 6);
    m_paLargeIcons->setEnabled(d->nearestIconSizeError(48) < 8);
    m_paHugeIcons->setEnabled(d->nearestIconSizeError(64) < 12);
    d->aEnormousIcons->setEnabled(d->findNearestIconSize(128) > 110);

    if (m_pProps) {
	int size = m_pProps->iconSize();
	int nearSize = d->findNearestIconSize(size);

	if (size != nearSize) {
	    m_pProps->setIconSize(nearSize);
	}
	newIconSize(nearSize);
    }
}

void KonqDirPart::setMimeFilter (const QStringList& mime)
{
    QString u = url().url();

    if ( u.isEmpty () )
        return;

    if ( mime.isEmpty() )
        d->mimeFilters.clear();
    else
        d->mimeFilters = mime;
}

QStringList KonqDirPart::mimeFilter() const
{
    return d->mimeFilters;
}

QScrollView * KonqDirPart::scrollWidget()
{
    return static_cast<QScrollView *>(widget());
}

void KonqDirPart::slotBackgroundSettings()
{
    QColor bgndColor = m_pProps->bgColor( widget() );
    QColor defaultColor = KGlobalSettings::baseColor();
    // dlg must be created on the heap as widget() can get deleted while dlg.exec(),
    // trying to delete dlg as its child then (#124210) - Frank Osterfeld
    QGuardedPtr<KonqBgndDialog> dlg = new KonqBgndDialog( widget(), 
                                              m_pProps->bgPixmapFile(),
                                              bgndColor,
                                              defaultColor );
    
    if ( dlg->exec() == KonqBgndDialog::Accepted )
    {
        if ( dlg->color().isValid() )
        {
            m_pProps->setBgColor( dlg->color() );
        m_pProps->setBgPixmapFile( "" );
    }
        else
    {
            m_pProps->setBgColor( defaultColor );
        m_pProps->setBgPixmapFile( dlg->pixmapFile() );
        }
        m_pProps->applyColors( scrollWidget()->viewport() );
        scrollWidget()->viewport()->repaint();
    }
    
    delete dlg;
}

void KonqDirPart::lmbClicked( KFileItem * fileItem )
{
    KURL url = fileItem->url();
    if ( !fileItem->isReadable() )
    {
        // No permissions or local file that doesn't exist - need to find out which
        if ( ( !fileItem->isLocalFile() ) || QFile::exists( url.path() ) )
        {
            KMessageBox::error( widget(), i18n("<p>You do not have enough permissions to read <b>%1</b></p>").arg(url.prettyURL()) );
            return;
        }
        KMessageBox::error( widget(), i18n("<p><b>%1</b> does not seem to exist anymore</p>").arg(url.prettyURL()) );
        return;
    }

    KParts::URLArgs args;
    fileItem->determineMimeType();
    if ( fileItem->isMimeTypeKnown() )
        args.serviceType = fileItem->mimetype();
    args.trustedSource = true;

    if (KonqFMSettings::settings()->alwaysNewWin() && fileItem->isDir()) {
        //args.frameName = "_blank"; // open new window
        // We tried the other option, passing the path as framename so that
        // an existing window for that dir is reused (like MSWindows does when
        // the similar option is activated and the sidebar is hidden (!)).
        // But this requires some work, including changing the framename
        // when navigating, etc. Not very much requested yet, in addition.
        KParts::WindowArgs wargs;
        KParts::ReadOnlyPart* dummy;
        emit m_extension->createNewWindow( url, args, wargs, dummy );
    }
    else
    {
        kdDebug() << "emit m_extension->openURLRequest( " << url.url() << "," << args.serviceType << ")" << endl;
        emit m_extension->openURLRequest( url, args );
    }
}

void KonqDirPart::mmbClicked( KFileItem * fileItem )
{
    if ( fileItem )
    {
        // Optimisation to avoid KRun to call kfmclient that then tells us
        // to open a window :-)
        KService::Ptr offer = KServiceTypeProfile::preferredService(fileItem->mimetype(), "Application");
        //if (offer) kdDebug(1203) << "KonqDirPart::mmbClicked: got service " << offer->desktopEntryName() << endl;
        if ( offer && offer->desktopEntryName().startsWith("kfmclient") )
        {
            KParts::URLArgs args;
            args.serviceType = fileItem->mimetype();
            emit m_extension->createNewWindow( fileItem->url(), args );
        }
        else
            fileItem->run();
    }
    else
    {
        m_extension->pasteRequest();
    }
}

void KonqDirPart::saveState( QDataStream& stream )
{
    stream << m_nameFilter;
}

void KonqDirPart::restoreState( QDataStream& stream )
{
    stream >> m_nameFilter;
}

void KonqDirPart::saveFindState( QDataStream& stream )
{
    // assert only doable in KDE4.
    //assert( m_findPart ); // test done by caller.
    if ( !m_findPart )
        return;

    // When we have a find part, our own URL wasn't saved (see KonqDirPartBrowserExtension)
    // So let's do it here
    stream << m_url;

    KParts::BrowserExtension* ext = KParts::BrowserExtension::childObject( m_findPart );
    if( !ext )
        return;

    ext->saveState( stream );
}

void KonqDirPart::restoreFindState( QDataStream& stream )
{
    // Restore our own URL
    stream >> m_url;

    emit findOpen( this );

    KParts::BrowserExtension* ext = KParts::BrowserExtension::childObject( m_findPart );
    slotClear();

    if( !ext )
        return;

    ext->restoreState( stream );
}

void KonqDirPart::slotClipboardDataChanged()
{
    // This is very related to KDIconView::slotClipboardDataChanged

    KURL::List lst;
    QMimeSource *data = QApplication::clipboard()->data();
    if ( data->provides( "application/x-kde-cutselection" ) && data->provides( "text/uri-list" ) )
        if ( KonqDrag::decodeIsCutSelection( data ) )
            (void) KURLDrag::decode( data, lst );

    disableIcons( lst );

    updatePasteAction();
}

void KonqDirPart::updatePasteAction() // KDE4: merge into method above
{
    QString actionText = KIO::pasteActionText();
    bool paste = !actionText.isEmpty();
    if ( paste )
      emit m_extension->setActionText( "paste", actionText );
    emit m_extension->enableAction( "paste", paste );
}

void KonqDirPart::newItems( const KFileItemList & entries )
{
    d->dirSizeDirty = true;
    if ( m_findPart )
        emitTotalCount();

    emit itemsAdded( entries );
}

void KonqDirPart::deleteItem( KFileItem * fileItem )
{
    d->dirSizeDirty = true;
    emit itemRemoved( fileItem );
}

void KonqDirPart::emitTotalCount()
{
    if ( !d->dirLister || d->dirLister->url().isEmpty() )
        return;
    if ( d->dirSizeDirty ) {
        m_lDirSize = 0;
        m_lFileCount = 0;
        m_lDirCount = 0;
        KFileItemList entries = d->dirLister->items();
        for (KFileItemListIterator it(entries); it.current(); ++it)
        {
            if ( !it.current()->isDir() )
            {
                if (!it.current()->isLink()) // symlinks don't contribute to the size
                    m_lDirSize += it.current()->size();
                m_lFileCount++;
            }
            else
                m_lDirCount++;
        }
        d->dirSizeDirty = false;
    }

    QString summary =
        KIO::itemsSummaryString(m_lFileCount + m_lDirCount,
                                m_lFileCount,
                                m_lDirCount,
                                m_lDirSize,
                                true);
    bool bShowsResult = false;
    if (m_findPart)
    {
        QVariant prop = m_findPart->property( "showsResult" );
        bShowsResult = prop.isValid() && prop.toBool();
    }
    //kdDebug(1203) << "KonqDirPart::emitTotalCount bShowsResult=" << bShowsResult << endl;
    emit setStatusBarText( bShowsResult ? i18n("Search result: %1").arg(summary) : summary );
}

void KonqDirPart::emitCounts( const KFileItemList & lst )
{
    if ( lst.count() == 1 )
        emit setStatusBarText( ((KFileItemList)lst).first()->getStatusBarInfo() );
    else
    {
        long long fileSizeSum = 0;
        uint fileCount = 0;
        uint dirCount = 0;

        for ( KFileItemListIterator it( lst ); it.current(); ++it )
        {
            if ( it.current()->isDir() )
                dirCount++;
            else
            {
                if ( !it.current()->isLink() ) // ignore symlinks
                    fileSizeSum += it.current()->size();
                fileCount++;
            }
        }

        emit setStatusBarText( KIO::itemsSummaryString( fileCount + dirCount,
                                                        fileCount, dirCount,
                                                        fileSizeSum, true ) );
    }
}

void KonqDirPart::emitCounts( const KFileItemList & lst, bool selectionChanged )
{
    if ( lst.count() == 0 )
        emitTotalCount();
    else
        emitCounts( lst );

    // Yes, the caller could do that too :)
    // But this bool could also be used to cache the QString for the last
    // selection, as long as selectionChanged is false.
    // Not sure it's worth it though.
    // MiB: no, I don't think it's worth it. Especially regarding the
    //      loss of readability of the code. Thus, this will be removed in
    //      KDE 4.0.
    if ( selectionChanged )
        emit m_extension->selectionInfo( lst );
}

void KonqDirPart::emitMouseOver( const KFileItem* item )
{
    emit m_extension->mouseOverInfo( item );
}

void KonqDirPart::slotIconSizeToggled( bool toggleOn )
{
    //kdDebug(1203) << "KonqDirPart::slotIconSizeToggled" << endl;

    // This slot is called when an iconsize action is checked or by calling
    // action->setChecked(false) (previously true). So we must filter out
    // the 'untoggled' case to prevent odd results here (repaints/loops!)
    if ( !toggleOn )
        return;

    if ( m_paDefaultIcons->isChecked() )
        setIconSize(0);
    else if ( d->aEnormousIcons->isChecked() )
        setIconSize(d->findNearestIconSize(KIcon::SizeEnormous));
    else if ( m_paHugeIcons->isChecked() )
        setIconSize(d->findNearestIconSize(KIcon::SizeHuge));
    else if ( m_paLargeIcons->isChecked() )
        setIconSize(d->findNearestIconSize(KIcon::SizeLarge));
    else if ( m_paMediumIcons->isChecked() )
        setIconSize(d->findNearestIconSize(KIcon::SizeMedium));
    else if ( d->aSmallMediumIcons->isChecked() )
        setIconSize(d->findNearestIconSize(KIcon::SizeSmallMedium));
    else if ( m_paSmallIcons->isChecked() )
        setIconSize(d->findNearestIconSize(KIcon::SizeSmall));
}

void KonqDirPart::slotIncIconSize()
{
    int s = m_pProps->iconSize();
    s = s ? s : KGlobal::iconLoader()->currentSize( KIcon::Desktop );
    uint sizeIndex = 0;
    for ( uint idx = 1; idx < d->iconSize.count() ; ++idx )
        if (s == d->iconSize[idx]) {
            sizeIndex = idx;
	    break;
	}
    if ( sizeIndex > 0 && sizeIndex < d->iconSize.count() - 1 )
    {
        setIconSize( d->iconSize[sizeIndex + 1] );
    }
}

void KonqDirPart::slotDecIconSize()
{
    int s = m_pProps->iconSize();
    s = s ? s : KGlobal::iconLoader()->currentSize( KIcon::Desktop );
    uint sizeIndex = 0;
    for ( uint idx = 1; idx < d->iconSize.count() ; ++idx )
        if (s == d->iconSize[idx]) {
            sizeIndex = idx;
	    break;
	}
    if ( sizeIndex > 1 )
    {
        setIconSize( d->iconSize[sizeIndex - 1] );
    }
}

// Only updates Actions, a GUI update is done in the views by reimplementing this
void KonqDirPart::newIconSize( int size /*0=default, or 16,32,48....*/ )
{
    int realSize = (size==0) ? KGlobal::iconLoader()->currentSize( KIcon::Desktop ) : size;
    m_paDecIconSize->setEnabled(realSize > d->iconSize[1]);
    m_paIncIconSize->setEnabled(realSize < d->iconSize.back());

    m_paDefaultIcons->setChecked(size == 0);
    d->aEnormousIcons->setChecked(size == d->findNearestIconSize(KIcon::SizeEnormous));
    m_paHugeIcons->setChecked(size == d->findNearestIconSize(KIcon::SizeHuge));
    m_paLargeIcons->setChecked(size == d->findNearestIconSize(KIcon::SizeLarge));
    m_paMediumIcons->setChecked(size == d->findNearestIconSize(KIcon::SizeMedium));
    d->aSmallMediumIcons->setChecked(size == d->findNearestIconSize(KIcon::SizeSmallMedium));
    m_paSmallIcons->setChecked(size == d->findNearestIconSize(KIcon::SizeSmall));
}

// Stores the new icon size and updates the GUI
void KonqDirPart::setIconSize( int size )
{
    //kdDebug(1203) << "KonqDirPart::setIconSize " << size << " -> updating props and GUI" << endl;
    m_pProps->setIconSize( size );
    newIconSize( size );
}

bool KonqDirPart::closeURL()
{
    // Tell all the childern objects to clean themselves up for dinner :)
    return doCloseURL();
}

bool KonqDirPart::openURL(const KURL& url)
{
    if ( m_findPart )
    {
        kdDebug(1203) << "KonqDirPart::openURL -> emit findClosed " << this << endl;
        delete m_findPart;
        m_findPart = 0L;
        emit findClosed( this );
    }

    m_url = url;
    emit aboutToOpenURL ();

    return doOpenURL(url);
}

void KonqDirPart::setFindPart( KParts::ReadOnlyPart * part )
{
    assert(part);
    m_findPart = part;
    connect( m_findPart, SIGNAL( started() ),
             this, SLOT( slotStarted() ) );
    connect( m_findPart, SIGNAL( started() ),
             this, SLOT( slotStartAnimationSearching() ) );
    connect( m_findPart, SIGNAL( clear() ),
             this, SLOT( slotClear() ) );
    connect( m_findPart, SIGNAL( newItems( const KFileItemList & ) ),
             this, SLOT( slotNewItems( const KFileItemList & ) ) );
    connect( m_findPart, SIGNAL( finished() ), // can't name it completed, it conflicts with a KROP signal
             this, SLOT( slotCompleted() ) );
    connect( m_findPart, SIGNAL( finished() ),
             this, SLOT( slotStopAnimationSearching() ) );
    connect( m_findPart, SIGNAL( canceled() ),
             this, SLOT( slotCanceled() ) );
    connect( m_findPart, SIGNAL( canceled() ),
             this, SLOT( slotStopAnimationSearching() ) );

    connect( m_findPart, SIGNAL( findClosed() ),
             this, SLOT( slotFindClosed() ) );

    emit findOpened( this );

    // set the initial URL in the find part
    m_findPart->openURL( url() );
}

void KonqDirPart::slotFindClosed()
{
    kdDebug(1203) << "KonqDirPart::slotFindClosed -> emit findClosed " << this << endl;
    delete m_findPart;
    m_findPart = 0L;
    emit findClosed( this );
    // reload where we were before
    openURL( url() );
}

void KonqDirPart::slotIconChanged( int group )
{
    if (group != KIcon::Desktop) return;
    adjustIconSizes();
}

void KonqDirPart::slotStartAnimationSearching()
{
  started(0);
}

void KonqDirPart::slotStopAnimationSearching()
{
  completed();
}

void KonqDirPartBrowserExtension::saveState( QDataStream &stream )
{
    m_dirPart->saveState( stream );
    bool hasFindPart = m_dirPart->findPart();
    stream << hasFindPart;
    assert( ! ( hasFindPart && !strcmp(m_dirPart->className(), "KFindPart") ) );
    if ( !hasFindPart )
        KParts::BrowserExtension::saveState( stream );
    else {
        m_dirPart->saveFindState( stream );
    }
}

void KonqDirPartBrowserExtension::restoreState( QDataStream &stream )
{
    m_dirPart->restoreState( stream );
    bool hasFindPart;
    stream >> hasFindPart;
    assert( ! ( hasFindPart && !strcmp(m_dirPart->className(), "KFindPart") ) );
    if ( !hasFindPart )
        // This calls openURL, that's why we don't want to call it in case of a find part
        KParts::BrowserExtension::restoreState( stream );
    else {
        m_dirPart->restoreFindState( stream );
    }
}


void KonqDirPart::resetCount()
{
    m_lDirSize = 0;
    m_lFileCount = 0;
    m_lDirCount = 0;
    d->dirSizeDirty = true;
}

void KonqDirPart::setDirLister( KDirLister* lister )
{
    d->dirLister = lister;
}

#include "konq_dirpart.moc"
