// kmfoldertree.cpp
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "kmfoldertree.h"

#include "kmfoldermgr.h"
#include "kmfolder.h"
#include "kmfolderimap.h"
#include "kmfoldercachedimap.h"
#include "kmfolderdia.h"
#include "kmheaders.h"
#include "kmmainwidget.h"
#include "kmailicalifaceimpl.h"
#include "accountmanager.h"
using KMail::AccountManager;
#include "globalsettings.h"
#include "kmcommands.h"
#include "foldershortcutdialog.h"
#include "expirypropertiesdialog.h"
#include "newfolderdialog.h"
#include "acljobs.h"
#include "messagecopyhelper.h"
using KMail::MessageCopyHelper;
#include "favoritefolderview.h"
#include "folderviewtooltip.h"
using KMail::FolderViewToolTip;

#include <maillistdrag.h>
using namespace KPIM;

#include <tdeapplication.h>
#include <tdeglobalsettings.h>
#include <kiconloader.h>
#include <tdemessagebox.h>
#include <tdeconfig.h>
#include <tdepopupmenu.h>
#include <kdebug.h>

#include <tqpainter.h>
#include <tqcursor.h>
#include <tqregexp.h>
#include <tqpopupmenu.h>

#include <unistd.h>
#include <assert.h>

#include <X11/Xlib.h>
#include <fixx11h.h>

//=============================================================================

KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const TQString & name,
                                    KFolderTreeItem::Protocol protocol )
  : TQObject( parent, name.latin1() ),
    KFolderTreeItem( parent, name, protocol, Root ),
    mFolder( 0 ), mNeedsRepaint( true )
{
  init();
  setPixmap( 0, normalIcon( iconSize() ) );
}

//-----------------------------------------------------------------------------
KMFolderTreeItem::KMFolderTreeItem( KFolderTree *parent, const TQString & name,
                    KMFolder* folder )
  : TQObject( parent, name.latin1() ),
    KFolderTreeItem( parent, name ),
    mFolder( folder ), mNeedsRepaint( true )
{
  init();
  setPixmap( 0, normalIcon( iconSize() ) );
}

//-----------------------------------------------------------------------------
KMFolderTreeItem::KMFolderTreeItem( KFolderTreeItem *parent, const TQString & name,
                    KMFolder* folder )
  : TQObject( 0, name.latin1() ),
    KFolderTreeItem( parent, name ),
    mFolder( folder ), mNeedsRepaint( true )
{
  init();
  setPixmap( 0, normalIcon( iconSize() ) );
}

KMFolderTreeItem::~KMFolderTreeItem()
{
}

static KFolderTreeItem::Protocol protocolFor( KMFolderType t ) {
  switch ( t ) {
  case KMFolderTypeImap:
    return KFolderTreeItem::Imap;
  case KMFolderTypeCachedImap:
    return KFolderTreeItem::CachedImap;
  case KMFolderTypeMbox:
  case KMFolderTypeMaildir:
    return KFolderTreeItem::Local;
  case KMFolderTypeSearch:
    return KFolderTreeItem::Search;
  default:
    return KFolderTreeItem::NONE;
  }
}

TQPixmap KMFolderTreeItem::normalIcon(int size) const
{
  TQString icon;
  if ( (!mFolder && type() == Root) || useTopLevelIcon() ) {
    switch ( protocol() ) {
      case KFolderTreeItem::Imap:
      case KFolderTreeItem::CachedImap:
      case KFolderTreeItem::News:
        icon = "server"; break;
      case KFolderTreeItem::Search:
        icon = "viewmag";break;
      default:
        icon = "folder";break;
    }
  } else {
    // special folders
    switch ( type() ) {
      case Inbox: icon = "folder_inbox"; break;
      case Outbox: icon = "folder_outbox"; break;
      case SentMail: icon = "folder_sent_mail"; break;
      case Trash: icon = "trashcan_empty"; break;
      case Drafts: icon = "edit"; break;
      case Templates: icon = "document-new"; break;
      default:
      {
        //If not a resource folder don't try to use icalIface folder pixmap
        if(kmkernel->iCalIface().isResourceFolder( mFolder ))
          icon = kmkernel->iCalIface().folderPixmap( type() );
        break;
      }
    }
    // non-root search folders
    if ( protocol() == KMFolderTreeItem::Search ) {
      icon = "mail_find";
    }
    if ( mFolder && mFolder->noContent() ) {
      icon = "folder_grey";
    }
  }

  if ( icon.isEmpty() )
    icon = "folder";

  if (mFolder && mFolder->useCustomIcons() ) {
    icon = mFolder->normalIconPath();
  }
  TDEIconLoader * il = TDEGlobal::instance()->iconLoader();
  TQPixmap pm = il->loadIcon( icon, TDEIcon::Small, size,
                             TDEIcon::DefaultState, 0, true );
  if ( mFolder && pm.isNull() ) {
      pm = il->loadIcon( mFolder->normalIconPath(), TDEIcon::Small, size,
                         TDEIcon::DefaultState, 0, true );
  }

  return pm;
}

TQPixmap KMFolderTreeItem::unreadIcon(int size) const
{
  TQPixmap pm;

  if ( !mFolder || useTopLevelIcon() || mFolder->isSystemFolder() ||
       kmkernel->folderIsTrash( mFolder ) ||
       kmkernel->folderIsTemplates( mFolder ) ||
       kmkernel->folderIsDraftOrOutbox( mFolder ) )
    pm = normalIcon( size );

  TDEIconLoader * il = TDEGlobal::instance()->iconLoader();
  if ( mFolder && mFolder->useCustomIcons() ) {
    pm = il->loadIcon( mFolder->unreadIconPath(), TDEIcon::Small, size,
                       TDEIcon::DefaultState, 0, true );
    if ( pm.isNull() )
      pm = il->loadIcon( mFolder->normalIconPath(), TDEIcon::Small, size,
                         TDEIcon::DefaultState, 0, true );
  }
  if ( pm.isNull() ) {
    if ( mFolder && mFolder->noContent() ) {
      pm = il->loadIcon( "folder_grey_open", TDEIcon::Small, size,
                         TDEIcon::DefaultState, 0, true );
    } else {
      if( kmkernel->iCalIface().isResourceFolder( mFolder ) )
        pm = il->loadIcon( kmkernel->iCalIface().folderPixmap( type() ),
                         TDEIcon::Small, size, TDEIcon::DefaultState, 0, true );
      if ( pm.isNull() )
        pm = il->loadIcon( "folder_open", TDEIcon::Small, size,
                           TDEIcon::DefaultState, 0, true );
    }
  }

  return pm;
}

void KMFolderTreeItem::init()
{
  if ( !mFolder )
    return;

  setProtocol( protocolFor( mFolder->folderType() ) );

  if ( useTopLevelIcon() )
    setType(Root);
  else {
    if ( mFolder == kmkernel->inboxFolder() )
      setType( Inbox );
    else if ( kmkernel->folderIsDraftOrOutbox( mFolder ) ) {
      if ( mFolder == kmkernel->outboxFolder() )
        setType( Outbox );
      else
        setType( Drafts );
    }
    else if ( kmkernel->folderIsSentMailFolder( mFolder ) )
      setType( SentMail );
    else if ( kmkernel->folderIsTrash( mFolder ) )
      setType( Trash );
    else if ( kmkernel->folderIsTemplates( mFolder ) )
      setType( Templates );
    else if( kmkernel->iCalIface().isResourceFolder(mFolder) )
      setType( kmkernel->iCalIface().folderType(mFolder) );
    // System folders on dimap or imap which are not resource folders are
    // inboxes. Urgs.
    if ( mFolder->isSystemFolder() &&
        !kmkernel->iCalIface().isResourceFolder( mFolder) &&
         ( mFolder->folderType() == KMFolderTypeImap
        || mFolder->folderType() == KMFolderTypeCachedImap ) )
      setType( Inbox );
  }
  if ( !mFolder->isSystemFolder() )
    setRenameEnabled( 0, false );

  KMFolderTree* tree = dynamic_cast<KMFolderTree*>( listView() );
  if ( tree )
    tree->insertIntoFolderToItemMap( mFolder, this );
}

void KMFolderTreeItem::adjustUnreadCount( int newUnreadCount ) {
  // adjust the icons if the folder is now newly unread or
  // now newly not-unread
  if ( newUnreadCount != 0 && unreadCount() == 0 )
    setPixmap( 0, unreadIcon( iconSize() ) );
  if ( unreadCount() != 0 && newUnreadCount == 0 )
    setPixmap( 0, normalIcon( iconSize() ) );

  setUnreadCount( newUnreadCount );
}

void KMFolderTreeItem::slotIconsChanged()
{
  kdDebug(5006) << k_funcinfo << endl;
  // this is prone to change, so better check
  KFolderTreeItem::Type newType = type();
  if( kmkernel->iCalIface().isResourceFolder( mFolder ) )
    newType = kmkernel->iCalIface().folderType(mFolder);

  // reload the folder tree if the type changed, needed because of the
  // various type-dependent folder hiding options
  if ( type() != newType )
    static_cast<KMFolderTree*>( listView() )->delayedReload();
  setType( newType );

  if ( unreadCount() > 0 )
    setPixmap( 0, unreadIcon( iconSize() ) );
  else
    setPixmap( 0, normalIcon( iconSize() ) );
  emit iconChanged( this );
  repaint();
}

void KMFolderTreeItem::slotNameChanged()
{
  setText( 0, mFolder->label() );
  emit nameChanged( this );
  repaint();
}

void KMFolderTreeItem::slotNoContentChanged()
{
  // reload the folder tree if the no content state changed, needed because
  // we hide no-content folders if their child nodes are hidden
  TQTimer::singleShot( 0, static_cast<KMFolderTree*>( listView() ), TQT_SLOT(reload()) );
}

//-----------------------------------------------------------------------------
bool KMFolderTreeItem::acceptDrag(TQDropEvent* e) const
{
  // Do not allow drags from the favorite folder view, as they don't really
  // make sense and do not work.
  KMMainWidget *mainWidget = static_cast<KMFolderTree*>( listView() )->mainWidget();
  assert( mainWidget );
  if ( mainWidget->favoriteFolderView() &&
       e->source() == mainWidget->favoriteFolderView()->viewport() )
    return false;

  if ( protocol() == KFolderTreeItem::Search )
    return false; // nothing can be dragged into search folders

  if ( e->provides( KPIM::MailListDrag::format() ) ) {
    if ( !mFolder || mFolder->moveInProgress() || mFolder->isReadOnly() ||
        (mFolder->noContent() && childCount() == 0) ||
        (mFolder->noContent() && isOpen()) ) {
      return false;
    }
    else {
      return true;
    }
  } else if ( e->provides("application/x-qlistviewitem") ) {
    // wtf: protocol() is NONE instead of Local for the local root folder
    if ( !mFolder && protocol() == KFolderTreeItem::NONE && type() == KFolderTreeItem::Root )
      return true; // local top-level folder
    if ( !mFolder || mFolder->isReadOnly() || mFolder->noContent() )
      return false;
    return true;
  }
  return false;
}

//-----------------------------------------------------------------------------
void KMFolderTreeItem::slotShowExpiryProperties()
{
  if ( !mFolder )
    return;

  KMFolderTree* tree = static_cast<KMFolderTree*>( listView() );
  KMail::ExpiryPropertiesDialog *dlg =
    new KMail::ExpiryPropertiesDialog( tree, mFolder );
  dlg->show();
}


//-----------------------------------------------------------------------------
void KMFolderTreeItem::properties()
{
  if ( !mFolder )
    return;

  KMail::FolderTreeBase* tree = static_cast<KMail::FolderTreeBase*>( listView() );
  tree->mainWidget()->modifyFolder( this );
  //Nothing here the above may actually delete this KMFolderTreeItem
}

//-----------------------------------------------------------------------------
void KMFolderTreeItem::assignShortcut()
{
  if ( !mFolder )
    return;

  KMail::FolderShortcutDialog *shorty =
    new KMail::FolderShortcutDialog( mFolder,
              kmkernel->getKMMainWidget(),
              listView() );
  shorty->exec();
  delete shorty;
}

//-----------------------------------------------------------------------------
void KMFolderTreeItem::updateCount()
{
    if ( !folder() ) {
      setTotalCount( -1 );
      return;
    }
    KMail::FolderTreeBase* tree = dynamic_cast<KMail::FolderTreeBase*>( listView() );
    if ( !tree ) return;

    tree->slotUpdateCounts( folder(), true /* force update */ );
}


//=============================================================================


KMFolderTree::KMFolderTree( KMMainWidget *mainWidget, TQWidget *parent,
                            const char *name )
  : KMail::FolderTreeBase( mainWidget, parent, name )
  , mUpdateTimer( 0, "mUpdateTimer" )
  , autoopen_timer( 0, "autoopen_timer" )
{
  oldSelected = 0;
  oldCurrent = 0;
  mLastItem = 0;
  dropItem = 0;
  mMainWidget = mainWidget;
  mReloading = false;
  mCutFolder = false;

  mUpdateCountTimer= new TQTimer( this, "mUpdateCountTimer" );

  setDragEnabled( true );
  addAcceptableDropMimetype( "application/x-qlistviewitem", false );

  setSelectionModeExt( Extended );

  int namecol = addColumn( i18n("Folder"), 250 );
  header()->setStretchEnabled( true, namecol );
  setResizeMode( TQListView::NoColumn );
  // connect
  connectSignals();

  // popup to switch columns
  header()->setClickEnabled(true);
  header()->installEventFilter(this);
  mPopup = new TDEPopupMenu(this);
  mPopup->insertTitle(i18n("View Columns"));
  mPopup->setCheckable(true);
  mUnreadPop = mPopup->insertItem(i18n("Unread Column"), this, TQT_SLOT(slotToggleUnreadColumn()));
  mTotalPop = mPopup->insertItem(i18n("Total Column"), this, TQT_SLOT(slotToggleTotalColumn()));
  mSizePop = mPopup->insertItem(i18n("Size Column"), this, TQT_SLOT(slotToggleSizeColumn()));

  connect( this, TQT_SIGNAL( triggerRefresh() ),
           this, TQT_SLOT( refresh() ) );

  new FolderViewToolTip( this );
}

//-----------------------------------------------------------------------------
// connects all needed signals to their slots
void KMFolderTree::connectSignals()
{
  connect( mUpdateCountTimer, TQT_SIGNAL(timeout()),
          this, TQT_SLOT(slotUpdateCountTimeout()) );

  connect(&mUpdateTimer, TQT_SIGNAL(timeout()),
          this, TQT_SLOT(delayedUpdate()));

  connect(kmkernel->folderMgr(), TQT_SIGNAL(changed()),
          this, TQT_SLOT(doFolderListChanged()));

  connect(kmkernel->folderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)),
          this, TQT_SLOT(slotFolderRemoved(KMFolder*)));

  connect(kmkernel->folderMgr(), TQT_SIGNAL(folderMoveOrCopyOperationFinished()),
	  this, TQT_SLOT(slotFolderMoveOrCopyOperationFinished()));

  connect(kmkernel->imapFolderMgr(), TQT_SIGNAL(changed()),
          this, TQT_SLOT(doFolderListChanged()));

  connect(kmkernel->imapFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)),
          this, TQT_SLOT(slotFolderRemoved(KMFolder*)));

  connect(kmkernel->dimapFolderMgr(), TQT_SIGNAL(changed()),
          this, TQT_SLOT(doFolderListChanged()));

  connect(kmkernel->dimapFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)),
          this, TQT_SLOT(slotFolderRemoved(KMFolder*)));

  connect(kmkernel->searchFolderMgr(), TQT_SIGNAL(changed()),
          this, TQT_SLOT(doFolderListChanged()));

  connect(kmkernel->acctMgr(), TQT_SIGNAL(accountRemoved(KMAccount*)),
          this, TQT_SLOT(slotAccountRemoved(KMAccount*)));

  connect(kmkernel->acctMgr(), TQT_SIGNAL(accountAdded(KMAccount*)),
          this, TQT_SLOT(slotUnhideLocalInbox()));

  connect(kmkernel->searchFolderMgr(), TQT_SIGNAL(folderRemoved(KMFolder*)),
          this, TQT_SLOT(slotFolderRemoved(KMFolder*)));

  connect( &autoopen_timer, TQT_SIGNAL( timeout() ),
           this, TQT_SLOT( openFolder() ) );

  connect( this, TQT_SIGNAL( contextMenuRequested( TQListViewItem*, const TQPoint &, int ) ),
           this, TQT_SLOT( slotContextMenuRequested( TQListViewItem*, const TQPoint & ) ) );

  connect( this, TQT_SIGNAL( expanded( TQListViewItem* ) ),
           this, TQT_SLOT( slotFolderExpanded( TQListViewItem* ) ) );

  connect( this, TQT_SIGNAL( collapsed( TQListViewItem* ) ),
           this, TQT_SLOT( slotFolderCollapsed( TQListViewItem* ) ) );

  connect( this, TQT_SIGNAL( itemRenamed( TQListViewItem*, int, const TQString &)),
           this, TQT_SLOT( slotRenameFolder( TQListViewItem*, int, const TQString &)));

  connect( this, TQT_SIGNAL(folderSelected(KMFolder*)), TQT_SLOT(updateCopyActions()) );
}

//-----------------------------------------------------------------------------
void KMFolderTree::readConfig (void)
{
  TDEConfig* conf = KMKernel::config();

  readColorConfig();

  // Custom/Ssystem font support
  {
    TDEConfigGroupSaver saver(conf, "Fonts");
    if (!conf->readBoolEntry("defaultFonts",true)) {
      TQFont folderFont( TDEGlobalSettings::generalFont() );
      setFont(conf->readFontEntry("folder-font", &folderFont));
    }
    else
      setFont(TDEGlobalSettings::generalFont());
  }

  // restore the layout
  restoreLayout(conf, "Geometry");
}

//-----------------------------------------------------------------------------
// Save the configuration file
void KMFolderTree::writeConfig()
{
  // save the current state of the folders
  for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) {
    KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
    if (fti)
      writeIsListViewItemOpen(fti);
  }

  // save the current layout
  saveLayout(KMKernel::config(), "Geometry");
}

//-----------------------------------------------------------------------------
// Updates the count of unread messages (count of unread messages
// is now cached in KMails config file)
void KMFolderTree::updateUnreadAll()
{
  bool upd = isUpdatesEnabled();
  setUpdatesEnabled(false);

  KMFolderDir* fdir;
  KMFolderNode* folderNode;
  KMFolder* folder;

  fdir = &kmkernel->folderMgr()->dir();
  for (folderNode = fdir->first();
    folderNode != 0;
    folderNode =fdir->next())
  {
    if (!folderNode->isDir()) {
      folder = static_cast<KMFolder*>(folderNode);

      folder->open("updateunread");
      folder->countUnread();
      folder->close("updateunread");
    }
  }

  setUpdatesEnabled(upd);
}

//-----------------------------------------------------------------------------
// Reload the tree of items in the list view
void KMFolderTree::reload(bool openFolders)
{
  if ( mReloading ) {
    // no parallel reloads are allowed
    kdDebug(5006) << "KMFolderTree::reload - already reloading" << endl;
    return;
  }
  mReloading = true;

  int top = contentsY();
  mLastItem = 0;
  // invalidate selected drop item
  oldSelected = 0;
  // remember last
  KMFolder* last = currentFolder();
  KMFolder* selected = 0;
  KMFolder* oldCurrentFolder =
    ( oldCurrent ? static_cast<KMFolderTreeItem*>(oldCurrent)->folder(): 0 );
  for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) {
    KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current());
    writeIsListViewItemOpen( fti );
    if ( fti->isSelected() )
      selected = fti->folder();
  }
  mFolderToItem.clear();
  clear();

  // construct the root of the local folders
  KMFolderTreeItem * root = new KMFolderTreeItem( this, i18n("Local Folders") );
  root->setOpen( readIsListViewItemOpen(root) );

  KMFolderDir * fdir = &kmkernel->folderMgr()->dir();
  addDirectory(fdir, root);

  fdir = &kmkernel->imapFolderMgr()->dir();
  // each imap-account creates it's own root
  addDirectory(fdir, 0);

  fdir = &kmkernel->dimapFolderMgr()->dir();
  // each dimap-account creates it's own root
  addDirectory(fdir, 0);

  // construct the root of the search folder hierarchy:
  root = new KMFolderTreeItem( this, i18n("Searches"), KFolderTreeItem::Search );
  root->setOpen( readIsListViewItemOpen( root ) );

  fdir = &kmkernel->searchFolderMgr()->dir();
  addDirectory(fdir, root);

  if (openFolders)
  {
    // we open all folders to update the count
    mUpdateIterator = TQListViewItemIterator (this);
    TQTimer::singleShot( 0, this, TQT_SLOT(slotUpdateOneCount()) );
  }

  for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) {
    KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current());
    if ( !fti || !fti->folder() )
      continue;

    disconnect(fti->folder(),TQT_SIGNAL(iconsChanged()),
               fti,TQT_SLOT(slotIconsChanged()));
    connect(fti->folder(),TQT_SIGNAL(iconsChanged()),
            fti,TQT_SLOT(slotIconsChanged()));

    disconnect(fti->folder(),TQT_SIGNAL(nameChanged()),
               fti,TQT_SLOT(slotNameChanged()));
    connect(fti->folder(),TQT_SIGNAL(nameChanged()),
            fti,TQT_SLOT(slotNameChanged()));

    disconnect( fti->folder(), TQT_SIGNAL(noContentChanged()),
                fti, TQT_SLOT(slotNoContentChanged()) );
    connect( fti->folder(), TQT_SIGNAL(noContentChanged()),
             fti, TQT_SLOT(slotNoContentChanged()) );

    disconnect( fti->folder(), TQT_SIGNAL(syncStateChanged()),
                this, TQT_SLOT(slotSyncStateChanged()) );
    connect( fti->folder(), TQT_SIGNAL(syncStateChanged()),
             this, TQT_SLOT(slotSyncStateChanged()) );

    // we want to be noticed of changes to update the unread/total columns
    disconnect(fti->folder(), TQT_SIGNAL(msgAdded(KMFolder*,TQ_UINT32)),
        this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
    connect(fti->folder(), TQT_SIGNAL(msgAdded(KMFolder*,TQ_UINT32)),
        this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
    //}

    disconnect(fti->folder(), TQT_SIGNAL(numUnreadMsgsChanged(KMFolder*)),
               this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
    connect(fti->folder(), TQT_SIGNAL(numUnreadMsgsChanged(KMFolder*)),
            this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
    disconnect(fti->folder(), TQT_SIGNAL(msgRemoved(KMFolder*)),
               this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
    connect(fti->folder(), TQT_SIGNAL(msgRemoved(KMFolder*)),
            this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));

  disconnect(fti->folder(), TQT_SIGNAL(folderSizeChanged( KMFolder* )),
               this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));
  connect(fti->folder(), TQT_SIGNAL(folderSizeChanged( KMFolder* )),
               this,TQT_SLOT(slotUpdateCountsDelayed(KMFolder*)));



    disconnect(fti->folder(), TQT_SIGNAL(shortcutChanged(KMFolder*)),
               mMainWidget, TQT_SLOT( slotShortcutChanged(KMFolder*)));
    connect(fti->folder(), TQT_SIGNAL(shortcutChanged(KMFolder*)),
            mMainWidget, TQT_SLOT( slotShortcutChanged(KMFolder*)));


    if (!openFolders)
      slotUpdateCounts(fti->folder());

    // populate the size column
    fti->setFolderSize( 0 );
    fti->setFolderIsCloseToQuota( fti->folder()->storage()->isCloseToQuota() );

  }
  ensureVisible(0, top + visibleHeight(), 0, 0);
  // if current and selected folder did not change set it again
  for ( TQListViewItemIterator it( this ) ; it.current() ; ++it )
  {
    if ( last &&
         static_cast<KMFolderTreeItem*>( it.current() )->folder() == last )
    {
      mLastItem = static_cast<KMFolderTreeItem*>( it.current() );
      setCurrentItem( it.current() );
    }
    if ( selected &&
         static_cast<KMFolderTreeItem*>( it.current() )->folder() == selected )
    {
      setSelected( it.current(), true );
    }
    if ( oldCurrentFolder &&
         static_cast<KMFolderTreeItem*>( it.current() )->folder() == oldCurrentFolder )
    {
      oldCurrent = it.current();
    }
  }
  refresh();
  mReloading = false;
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotUpdateOneCount()
{
  if ( !mUpdateIterator.current() ) return;
  KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(mUpdateIterator.current());
  ++mUpdateIterator;
  if ( !fti->folder() ) {
    // next one please
    TQTimer::singleShot( 0, this, TQT_SLOT(slotUpdateOneCount()) );
    return;
  }

  // open the folder and update the count
  bool open = fti->folder()->isOpened();
  if (!open) fti->folder()->open("updatecount");
  slotUpdateCounts(fti->folder());
  // restore previous state
  if (!open) fti->folder()->close("updatecount");

  TQTimer::singleShot( 0, this, TQT_SLOT(slotUpdateOneCount()) );
}

//-----------------------------------------------------------------------------
// Recursively add a directory of folders to the tree of folders
void KMFolderTree::addDirectory( KMFolderDir *fdir, KMFolderTreeItem* parent )
{
  for ( KMFolderNode * node = fdir->first() ; node ; node = fdir->next() ) {
    if ( node->isDir() )
      continue;

    KMFolder * folder = static_cast<KMFolder*>(node);
    KMFolderTreeItem * fti = 0;
    if (!parent)
    {
      // create new root-item, but only if this is not the root of a
      // "groupware folders only" account
      if ( kmkernel->iCalIface().hideResourceAccountRoot( folder ) )
        continue;
      // it needs a folder e.g. to save it's state (open/close)
      fti = new KMFolderTreeItem( this, folder->label(), folder );
      fti->setExpandable( true );

      // add child-folders
      if (folder && folder->child()) {
        addDirectory( folder->child(), fti );
      }
    } else {
      // hide local inbox if unused
      if ( kmkernel->inboxFolder() == folder && hideLocalInbox() ) {
        connect( kmkernel->inboxFolder(), TQT_SIGNAL(msgAdded(KMFolder*,TQ_UINT32)), TQT_SLOT(slotUnhideLocalInbox()) );
        continue;
      }

      // create new child
      fti = new KMFolderTreeItem( parent, folder->label(), folder );
      // set folders explicitely to exandable when they have children
      // this way we can do a listing for IMAP folders when the user expands them
      // even when the child folders are not created yet
      if ( folder->storage()->hasChildren() == FolderStorage::HasChildren ) {
        fti->setExpandable( true );
      } else {
        fti->setExpandable( false );
      }

      // add child-folders
      if (folder && folder->child()) {
        addDirectory( folder->child(), fti );
      }

      // Check if this is an IMAP resource folder or a no-content parent only
      // containing groupware folders
      if ( (kmkernel->iCalIface().hideResourceFolder( folder ) || folder->noContent())
            && fti->childCount() == 0 ) {
        // It is
        removeFromFolderToItemMap( folder );
        delete fti;
        // still, it might change in the future, so we better check the change signals
        connect ( folder, TQT_SIGNAL(noContentChanged()), TQT_SLOT(delayedReload()) );
        continue;
      }

      connect (fti, TQT_SIGNAL(iconChanged(KMFolderTreeItem*)),
          this, TQT_SIGNAL(iconChanged(KMFolderTreeItem*)));
      connect (fti, TQT_SIGNAL(nameChanged(KMFolderTreeItem*)),
          this, TQT_SIGNAL(nameChanged(KMFolderTreeItem*)));
    }
    // restore last open-state
    fti->setOpen( readIsListViewItemOpen(fti) );
  } // for-end
}

//-----------------------------------------------------------------------------
// Initiate a delayed refresh of the tree
void KMFolderTree::refresh()
{
  mUpdateTimer.changeInterval(200);
}

//-----------------------------------------------------------------------------
// Updates the pixmap and extendedLabel information for items
void KMFolderTree::delayedUpdate()
{
  bool upd = isUpdatesEnabled();
  if ( upd ) {
    setUpdatesEnabled(false);

    for ( TQListViewItemIterator it( this ) ; it.current() ; ++it ) {
      KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
      if (!fti || !fti->folder())
        continue;

      if ( fti->needsRepaint() ) {
        fti->repaint();
        fti->setNeedsRepaint( false );
      }
    }
    setUpdatesEnabled(upd);
  }
  mUpdateTimer.stop();
}

//-----------------------------------------------------------------------------
// Folders have been added/deleted update the tree of folders
void KMFolderTree::doFolderListChanged()
{
  reload();
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotAccountRemoved(KMAccount *)
{
  doFolderSelected( firstChild() );
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotFolderMoveOrCopyOperationFinished()
{
  setDragEnabled( true );
}
//-----------------------------------------------------------------------------
void KMFolderTree::slotFolderRemoved(KMFolder *aFolder)
{
  TQListViewItem *item = indexOfFolder(aFolder);
  if (!item) return;
  KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*> ( item );
  if ( oldCurrent == fti )
    oldCurrent = 0;
  if ( oldSelected == fti )
    oldSelected = 0;
  if (!fti || !fti->folder()) return;
  if (fti == currentItem())
  {
    TQListViewItem *qlvi = fti->itemAbove();
    if (!qlvi) qlvi = fti->itemBelow();
    doFolderSelected( qlvi );
  }
  removeFromFolderToItemMap( aFolder );

  if ( dropItem == fti ) { // The removed item is the dropItem
    dropItem = 0; // it becomes invalid
  }

  delete fti;
  updateCopyActions();
}

//-----------------------------------------------------------------------------
// Methods for navigating folders with the keyboard
void KMFolderTree::prepareItem( KMFolderTreeItem* fti )
{
  for ( TQListViewItem * parent = fti->parent() ; parent ; parent = parent->parent() )
    parent->setOpen( true );
  ensureItemVisible( fti );
}

//-----------------------------------------------------------------------------
void KMFolderTree::nextUnreadFolder()
{
    nextUnreadFolder( false );
}

//-----------------------------------------------------------------------------
void KMFolderTree::nextUnreadFolder(bool confirm)
{
  TQListViewItemIterator it( currentItem() ? currentItem() : firstChild() );
  if ( currentItem() )
    ++it; // don't find current item
  for ( ; it.current() ; ++it ) {
    //check if folder is one to stop on
    KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
    if (checkUnreadFolder(fti,confirm)) return;
  }
  //Now if confirm is true we are doing "ReadOn"
  //we have got to the bottom of the folder list
  //so we have to start at the top
  if (confirm) {
    for ( it = firstChild() ; it.current() ; ++it ) {
      //check if folder is one to stop on
      KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
      if (checkUnreadFolder(fti,confirm)) return;
    }
  }
}

//-----------------------------------------------------------------------------
bool KMFolderTree::checkUnreadFolder (KMFolderTreeItem* fti, bool confirm)
{
  if ( fti && fti->folder() && !fti->folder()->ignoreNewMail() &&
       ( fti->folder()->countUnread() > 0 ) ) {

    // Don't change into the trash or outbox folders.
    if (fti->type() == KFolderTreeItem::Trash ||
        fti->type() == KFolderTreeItem::Outbox )
      return false;

    if (confirm) {
      // Skip drafts, sent mail and templates as well, when reading mail with
      // the space bar but not when changing into the next folder with unread
      // mail via ctrl+ or ctrl- so we do this only if (confirm == true),
      // which means we are doing readOn.
      if ( fti->type() == KFolderTreeItem::Drafts ||
           fti->type() == KFolderTreeItem::Templates ||
           fti->type() == KFolderTreeItem::SentMail )
        return false;

      //  warn user that going to next folder - but keep track of
      //  whether he wishes to be notified again in "AskNextFolder"
      //  parameter (kept in the config file for kmail)
      if ( KMessageBox::questionYesNo( this,
            i18n( "<qt>Go to the next unread message in folder <b>%1</b>?</qt>" )
            .arg( fti->folder()->label() ),
            i18n( "Go to Next Unread Message" ),
            i18n("Go To"), i18n("Do Not Go To"), // defaults
            "AskNextFolder",
            false)
          == KMessageBox::No ) return true;
    }
    prepareItem( fti );
    blockSignals( true );
    doFolderSelected( fti );
    blockSignals( false );
    emit folderSelectedUnread( fti->folder() );
    return true;
  }
  return false;
}

//-----------------------------------------------------------------------------
void KMFolderTree::prevUnreadFolder()
{
  TQListViewItemIterator it( currentItem() ? currentItem() : lastItem() );
  if ( currentItem() )
    --it; // don't find current item
  for ( ; it.current() ; --it ) {
    KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
    if (checkUnreadFolder(fti,false)) return;
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::incCurrentFolder()
{
  TQListViewItemIterator it( currentItem() );
  ++it;
  KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
  if (fti) {
      prepareItem( fti );
      setFocus();
      setCurrentItem( fti );
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::decCurrentFolder()
{
  TQListViewItemIterator it( currentItem() );
  --it;
  KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(it.current());
  if (fti) {
      prepareItem( fti );
      setFocus();
      setCurrentItem( fti );
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::selectCurrentFolder()
{
  KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( currentItem() );
  if (fti) {
      prepareItem( fti );
      doFolderSelected( fti );
  }
}

//-----------------------------------------------------------------------------
KMFolder *KMFolderTree::currentFolder() const
{
    KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( currentItem() );
    if (fti )
        return fti->folder();
    else
        return 0;
}

TQValueList<TQGuardedPtr<KMFolder> > KMFolderTree::selectedFolders()
{
  TQValueList<TQGuardedPtr<KMFolder> > rv;
  for ( TQListViewItemIterator it( this ); it.current(); ++it ) {
    if ( it.current()->isSelected() ) {
      KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( it.current() );
      rv.append( fti->folder() );
    }
  }
  return rv;
}

//-----------------------------------------------------------------------------
// When not dragging and dropping a change in the selected item
// indicates the user has changed the active folder emit a signal
// so that the header list and reader window can be udpated.
void KMFolderTree::doFolderSelected( TQListViewItem* qlvi, bool keepSelection )
{
  if (!qlvi) return;
  if ( mLastItem && mLastItem == qlvi && (keepSelection || selectedFolders().count() == 1) )
    return;

  KMFolderTreeItem* fti = static_cast< KMFolderTreeItem* >(qlvi);
  KMFolder* folder = 0;
  if (fti) folder = fti->folder();

  if (mLastItem && mLastItem != fti && mLastItem->folder()
     && (mLastItem->folder()->folderType() == KMFolderTypeImap))
  {
    KMFolderImap *imapFolder = static_cast<KMFolderImap*>(mLastItem->folder()->storage());
    imapFolder->setSelected(false);
  }
  mLastItem = fti;

  if ( !keepSelection )
    clearSelection();
  setCurrentItem( qlvi );
  if ( !keepSelection )
    setSelected( qlvi, true );
  ensureItemVisible( qlvi );
  if (!folder) {
    emit folderSelected(0); // Root has been selected
  }
  else {
    emit folderSelected(folder);
    slotUpdateCounts(folder);
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::resizeEvent(TQResizeEvent* e)
{
  TDEConfig* conf = KMKernel::config();

  TDEConfigGroupSaver saver(conf, "Geometry");
  conf->writeEntry(name(), size().width());

  TDEListView::resizeEvent(e);
}

//-----------------------------------------------------------------------------
// show context menu
void KMFolderTree::slotContextMenuRequested( TQListViewItem *lvi,
                                             const TQPoint &p )
{
  if (!lvi)
    return;
  setCurrentItem( lvi );

  if (!mMainWidget) return; // safe bet

  KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(lvi);
  if ( !isSelected( fti ) )
    doFolderSelected( fti );
  else if ( fti != mLastItem )
    doFolderSelected( fti, true );

  if (!fti )
    return;

  TDEPopupMenu *folderMenu = new TDEPopupMenu;
  bool multiFolder = selectedFolders().count() > 1;
  if (fti->folder()) folderMenu->insertTitle(fti->folder()->label());

  // outbox specific, but there it's the most used action
  if ( (fti->folder() == kmkernel->outboxFolder()) && fti->folder()->count() )
        mMainWidget->action("send_queued")->plug( folderMenu );
  // Mark all as read is supposedly used often, therefor it is first
  if ( fti->folder() && !fti->folder()->noContent() )
      mMainWidget->action("mark_all_as_read")->plug( folderMenu );

  /* Treat the special case of the root and account folders */
  if ((!fti->folder() || (fti->folder()->noContent()
    && !fti->parent())))
  {
    TQString createChild = i18n("&New Subfolder...");
    if (!fti->folder()) createChild = i18n("&New Folder...");

    if ( ( fti->folder() || (fti->text(0) != i18n("Searches")) ) && !multiFolder)
        folderMenu->insertItem(SmallIconSet("folder-new"),
                               createChild, this,
                               TQT_SLOT(addChildFolder()));

    if (!fti->folder()) {
      mMainWidget->action("compact_all_folders")->plug(folderMenu);
      mMainWidget->action("expire_all_folders")->plug(folderMenu);
    } else if (fti->folder()->folderType() == KMFolderTypeImap) {
      folderMenu->insertItem(SmallIconSet("mail_get"), i18n("Check &Mail"),
        this,
        TQT_SLOT(slotCheckMail()));
    }
  } else { // regular folders

    folderMenu->insertSeparator();
    if ( !fti->folder()->noChildren() && !multiFolder ) {
      folderMenu->insertItem(SmallIconSet("folder-new"),
                             i18n("&New Subfolder..."), this,
                             TQT_SLOT(addChildFolder()));
    }

    // copy folder
    TQPopupMenu *copyMenu = new TQPopupMenu( folderMenu );
    folderToPopupMenu( CopyFolder, TQT_TQOBJECT(this), &mMenuToFolder, copyMenu );
    folderMenu->insertItem( i18n("&Copy Folder To"), copyMenu );

    if ( fti->folder()->isMoveable() && fti->folder()->canDeleteMessages() )
    {
      TQPopupMenu *moveMenu = new TQPopupMenu( folderMenu );
      folderToPopupMenu( MoveFolder, TQT_TQOBJECT(this), &mMenuToFolder, moveMenu );
      folderMenu->insertItem( i18n("&Move Folder To"), moveMenu );
    }

    // Want to be able to display properties for ALL folders,
    // so we can edit expiry properties.
    // -- smp.
    if (!fti->folder()->noContent())
    {
      if ( !multiFolder )
        mMainWidget->action("search_messages")->plug(folderMenu);

      mMainWidget->action( "archive_folder" )->plug( folderMenu );

      mMainWidget->action("compact")->plug(folderMenu);

      if ( GlobalSettings::self()->enableFavoriteFolderView() ) {
        folderMenu->insertItem( SmallIconSet("bookmark_add"), i18n("Add to Favorite Folders"),
                                this, TQT_SLOT(slotAddToFavorites()) );
      }

      folderMenu->insertSeparator();
      mMainWidget->action("empty")->plug(folderMenu);
      if ( !fti->folder()->isSystemFolder() ) {
        mMainWidget->action("delete_folder")->plug(folderMenu);
      }
      folderMenu->insertSeparator();
    }
  }

  /* plug in IMAP and DIMAP specific things */
  if (fti->folder() &&
      (fti->folder()->folderType() == KMFolderTypeImap ||
       fti->folder()->folderType() == KMFolderTypeCachedImap ))
  {
    folderMenu->insertItem(SmallIconSet("bookmark_folder"),
        i18n("Serverside Subscription..."), mMainWidget,
        TQT_SLOT(slotSubscriptionDialog()));
    folderMenu->insertItem(SmallIcon("bookmark_folder"),
        i18n("Local Subscription..."), mMainWidget,
        TQT_SLOT(slotLocalSubscriptionDialog()));

    if (!fti->folder()->noContent())
    {
      mMainWidget->action("refresh_folder")->plug(folderMenu);
      if ( fti->folder()->folderType() == KMFolderTypeImap && !multiFolder ) {
        folderMenu->insertItem(SmallIconSet("reload"), i18n("Refresh Folder List"), this,
            TQT_SLOT(slotResetFolderList()));
      }
    }
    if ( fti->folder()->folderType() == KMFolderTypeCachedImap && !multiFolder ) {
      KMFolderCachedImap * folder = static_cast<KMFolderCachedImap*>( fti->folder()->storage() );
      folderMenu->insertItem( SmallIconSet("wizard"),
                              i18n("&Troubleshoot IMAP Cache..."),
                              folder, TQT_SLOT(slotTroubleshoot()) );
    }
    folderMenu->insertSeparator();
  }

  if ( fti->folder() && fti->folder()->isMailingListEnabled() && !multiFolder ) {
    mMainWidget->action("post_message")->plug(folderMenu);
  }

  if (fti->folder() && fti->parent() && !multiFolder)
  {
    folderMenu->insertItem(SmallIconSet("configure_shortcuts"),
        i18n("&Assign Shortcut..."),
        fti,
        TQT_SLOT(assignShortcut()));

    if ( !fti->folder()->noContent() && fti->folder()->canDeleteMessages() ) {
      folderMenu->insertItem( i18n("Expire..."), fti,
                              TQT_SLOT( slotShowExpiryProperties() ) );
    }
    mMainWidget->action("modify")->plug(folderMenu);
  }


  kmkernel->setContextMenuShown( true );
  folderMenu->exec (p, 0);
  kmkernel->setContextMenuShown( false );
  triggerUpdate();
  delete folderMenu;
  folderMenu = 0;
}

//-----------------------------------------------------------------------------
void KMFolderTree::contentsMousePressEvent(TQMouseEvent * e)
{
  // KFolderTree messes around with the selection mode
  TDEListView::contentsMousePressEvent( e );
}

// If middle button and folder holds mailing-list, create a message to that list
void KMFolderTree::contentsMouseReleaseEvent(TQMouseEvent* me)
{
  TQListViewItem *lvi = currentItem(); // Needed for when branches are clicked on
  ButtonState btn = me->button();
  doFolderSelected(lvi, true);

  // get underlying folder
  KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>(lvi);

  if (!fti || !fti->folder()) {
    KFolderTree::contentsMouseReleaseEvent(me);
    return;
  }

  // react on middle-button only
  if (btn != Qt::MidButton) {
    KFolderTree::contentsMouseReleaseEvent(me);
    return;
  }

  if ( fti->folder()->isMailingListEnabled() ) {
    KMCommand *command = new KMMailingListPostCommand( this, fti->folder() );
    command->start();
  }

  KFolderTree::contentsMouseReleaseEvent(me);
}

// little static helper
static bool folderHasCreateRights( const KMFolder *folder )
{
  bool createRights = true; // we don't have acls for local folders yet
  if ( folder && folder->folderType() == KMFolderTypeImap ) {
    const KMFolderImap *imapFolder = static_cast<const KMFolderImap*>( folder->storage() );
    createRights = imapFolder->userRightsState() != KMail::ACLJobs::Ok || // hack, we should get the acls
      ( imapFolder->userRightsState() == KMail::ACLJobs::Ok &&
        ( imapFolder->userRights() & KMail::ACLJobs::Create ) );
  } else if ( folder && folder->folderType() == KMFolderTypeCachedImap ) {
    const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() );
    createRights = dimapFolder->userRightsState() != KMail::ACLJobs::Ok ||
      ( dimapFolder->userRightsState() == KMail::ACLJobs::Ok &&
        ( dimapFolder->userRights() & KMail::ACLJobs::Create ) );
  }
  return createRights;
}

//-----------------------------------------------------------------------------
// Create a subfolder.
// Requires creating the appropriate subdirectory and show a dialog
void KMFolderTree::addChildFolder( KMFolder *folder, TQWidget * parent )
{
  KMFolder *aFolder = folder;
  if ( !aFolder ) {
    KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(currentItem());
    if (!fti)
      return;
    aFolder = fti->folder();
  }
  if (aFolder) {
    if (!aFolder->createChildFolder())
      return;
    if ( !folderHasCreateRights( aFolder ) ) {
      const TQString message = i18n( "<qt>Cannot create folder under <b>%1</b> because of insufficient "
                                    "permissions on the server. If you think you should be able to create "
                                    "subfolders here, ask your administrator to grant you rights to do so."
                                    "</qt> " ).arg(aFolder->label());
      KMessageBox::error( this, message );
      return;
    }
  }

  if ( parent )
    ( new KMail::NewFolderDialog( parent, aFolder ) )->exec();
  else
    ( new KMail::NewFolderDialog( this, aFolder ) )->show();
  return;
/*
  KMFolderDir *dir = &(kmkernel->folderMgr()->dir());
  if (aFolder)
    dir = aFolder->child();

  KMFolderDialog *d =
    new KMFolderDialog(0, dir, this, i18n("Create Subfolder") );

  if (d->exec()) { // fti may be deleted here
    TQListViewItem *qlvi = indexOfFolder( aFolder );
    if (qlvi) {
      qlvi->setOpen(true);
      blockSignals( true );
      setCurrentItem( qlvi );
      blockSignals( false );
    }
  }
  delete d;
  // update if added to root Folder
  if (!aFolder || aFolder->noContent()) {
     doFolderListChanged();
  }
  */
}

//-----------------------------------------------------------------------------
// Returns whether a folder directory should be open as specified in the
// config file.
bool KMFolderTree::readIsListViewItemOpen(KMFolderTreeItem *fti)
{
  TDEConfig* config = KMKernel::config();
  KMFolder *folder = fti->folder();
  TQString name;
  if (folder)
  {
    name = "Folder-" + folder->idString();
  } else if (fti->type() == KFolderTreeItem::Root)
  {
    if (fti->protocol() == KFolderTreeItem::NONE) // local root
      name = "Folder_local_root";
    else if (fti->protocol() == KFolderTreeItem::Search)
      name = "Folder_search";
    else
      return false;
  } else {
    return false;
  }
  TDEConfigGroupSaver saver(config, name);

  return config->readBoolEntry("isOpen", false);
}

//-----------------------------------------------------------------------------
// Saves open/closed state of a folder directory into the config file
void KMFolderTree::writeIsListViewItemOpen(KMFolderTreeItem *fti)
{
  TDEConfig* config = KMKernel::config();
  KMFolder *folder = fti->folder();
  TQString name;
  if (folder && !folder->idString().isEmpty())
  {
    name = "Folder-" + folder->idString();
  } else if (fti->type() == KFolderTreeItem::Root)
  {
    if (fti->protocol() == KFolderTreeItem::NONE) // local root
      name = "Folder_local_root";
    else if (fti->protocol() == KFolderTreeItem::Search)
      name = "Folder_search";
    else
      return;
  } else {
    return;
  }
  TDEConfigGroupSaver saver(config, name);
  config->writeEntry("isOpen", fti->isOpen() );
}


//-----------------------------------------------------------------------------
void KMFolderTree::cleanupConfigFile()
{
  if ( childCount() == 0 )
    return; // just in case reload wasn't called before
  TDEConfig* config = KMKernel::config();
  TQStringList existingFolders;
  TQListViewItemIterator fldIt(this);
  TQMap<TQString,bool> folderMap;
  KMFolderTreeItem *fti;
  for (TQListViewItemIterator fldIt(this); fldIt.current(); fldIt++)
  {
    fti = static_cast<KMFolderTreeItem*>(fldIt.current());
    if (fti && fti->folder())
      folderMap.insert(fti->folder()->idString(), true);
  }
  TQStringList groupList = config->groupList();
  TQString name;
  for (TQStringList::Iterator grpIt = groupList.begin();
    grpIt != groupList.end(); grpIt++)
  {
    if ((*grpIt).left(7) != "Folder-") continue;
    name = (*grpIt).mid(7);
    if (folderMap.find(name) == folderMap.end())
    {
      KMFolder* folder = kmkernel->findFolderById( name );
      if ( folder ) {
        if ( kmkernel->iCalIface().hideResourceFolder( folder )
           ||  kmkernel->iCalIface().hideResourceAccountRoot( folder ) )
          continue; // hidden IMAP resource folder, don't delete info
        if ( folder->noContent() )
          continue; // we hide nocontent folders if they have no child folders
        if ( folder == kmkernel->inboxFolder() )
          continue; // local inbox can be hidden as well
      }

      //KMessageBox::error( 0, "cleanupConfigFile: Deleting group " + *grpIt );
      config->deleteGroup(*grpIt, true);
      kdDebug(5006) << "Deleting information about folder " << name << endl;
    }
  }
}


//-----------------------------------------------------------------------------
void KMFolderTree::openFolder()
{
    autoopen_timer.stop();
    if ( dropItem && !dropItem->isOpen() ) {
        dropItem->setOpen( true );
        dropItem->repaint();
    }
}

static const int autoopenTime = 750;

//-----------------------------------------------------------------------------
void KMFolderTree::contentsDragEnterEvent( TQDragEnterEvent *e )
{
  oldCurrent = 0;
  oldSelected = 0;

  oldCurrent = currentItem();
  for ( TQListViewItemIterator it( this ) ; it.current() ; ++it )
    if ( it.current()->isSelected() )
      oldSelected = it.current();

  setFocus();

  TQListViewItem *i = itemAt( contentsToViewport(e->pos()) );
  if ( i ) {
    dropItem = i;
    autoopen_timer.start( autoopenTime );
  }
  else
    dropItem = 0;

  e->accept( acceptDrag(e) );
}

//-----------------------------------------------------------------------------
void KMFolderTree::contentsDragMoveEvent( TQDragMoveEvent *e )
{
    TQPoint vp = contentsToViewport(e->pos());
    TQListViewItem *i = itemAt( vp );
    if ( i ) {
        bool dragAccepted = acceptDrag( e );
        if ( dragAccepted ) {
            setCurrentItem( i );
        }

        if ( i != dropItem ) {
            autoopen_timer.stop();
            dropItem = i;
            autoopen_timer.start( autoopenTime );
        }

        if ( dragAccepted ) {
            e->accept( itemRect(i) );

            switch ( e->action() ) {
                case TQDropEvent::Copy:
                break;
                case TQDropEvent::Move:
                e->acceptAction();
                break;
                case TQDropEvent::Link:
                e->acceptAction();
                break;
                default:
                ;
            }
        } else {
            e->accept( false );
        }
    } else {
        e->accept( false );
        autoopen_timer.stop();
        dropItem = 0;
    }
}

//-----------------------------------------------------------------------------
void KMFolderTree::contentsDragLeaveEvent( TQDragLeaveEvent * )
{
    if (!oldCurrent) return;

    autoopen_timer.stop();
    dropItem = 0;

    setCurrentItem( oldCurrent );
    if ( oldSelected )
      setSelected( oldSelected, true );
}

//-----------------------------------------------------------------------------
void KMFolderTree::contentsDropEvent( TQDropEvent *e )
{
    autoopen_timer.stop();

    TQListViewItem *item = itemAt( contentsToViewport(e->pos()) );
    KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
    // Check that each pointer is not null
    for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = mCopySourceFolders.constBegin();
	  it != mCopySourceFolders.constEnd(); ++it ) {
      if ( ! (*it) ) {
	fti = 0;
	break;
      }
    }
    if (fti && mCopySourceFolders.count() == 1)
    {
      KMFolder *source = mCopySourceFolders.first();
      // if we are dragging to ourselves or to our parent, set fti to 0 so nothing is done
      if (source == fti->folder() || source->parent()->owner() == fti->folder()) fti = 0;
    }
    if (fti && acceptDrag(e) && ( fti != oldSelected || e->source() != mMainWidget->headers()->viewport() ) )
    {
      if ( e->provides("application/x-qlistviewitem") ) {
        int action = dndMode( true /* always ask */ );
        if ( (action == DRAG_COPY || action == DRAG_MOVE) && !mCopySourceFolders.isEmpty() ) {
          for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = mCopySourceFolders.constBegin();
                it != mCopySourceFolders.constEnd(); ++it ) {
            if ( ! (*it)->isMoveable() )
              action = DRAG_COPY;
          }
          moveOrCopyFolder( mCopySourceFolders, fti->folder(), (action == DRAG_MOVE) );
        }
      } else {
        if ( e->source() == mMainWidget->headers()->viewport() ) {
          int action;
          if ( mMainWidget->headers()->folder() && mMainWidget->headers()->folder()->isReadOnly() )
            action = DRAG_COPY;
          else
            action = dndMode();
          // KMHeaders does copy/move itself
          if ( action == DRAG_MOVE && fti->folder() )
            emit folderDrop( fti->folder() );
          else if ( action == DRAG_COPY && fti->folder() )
            emit folderDropCopy( fti->folder() );
        } else {
          handleMailListDrop( e, fti->folder() );
        }
      }
      e->accept( true );
    } else
      e->accept( false );

    dropItem = 0;

    setCurrentItem( oldCurrent );
    if ( oldCurrent) mLastItem = static_cast<KMFolderTreeItem*>(oldCurrent);
    if ( oldSelected )
    {
      clearSelection();
      setSelected( oldSelected, true );
    }

    mCopySourceFolders.clear();
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotFolderExpanded( TQListViewItem * item )
{
  KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
  if ( !fti || !fti->folder() || !fti->folder()->storage() ) return;

  fti->setFolderSize( fti->folder()->storage()->folderSize() );

  if( fti->folder()->folderType() == KMFolderTypeImap )
  {
    KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() );
    // if we should list all folders we limit this to the root folder
    if ( !folder->account() || ( !folder->account()->listOnlyOpenFolders() &&
         fti->parent() ) )
      return;
    if ( folder->getSubfolderState() == KMFolderImap::imapNoInformation )
    {
      // check if all parents are expanded
      TQListViewItem *parent = item->parent();
      while ( parent )
      {
        if ( !parent->isOpen() )
          return;
        parent = parent->parent();
      }
      // the tree will be reloaded after that
      bool success = folder->listDirectory();
      if (!success) fti->setOpen( false );
      if ( fti->childCount() == 0 && fti->parent() )
        fti->setExpandable( false );
    }
  }
}


//-----------------------------------------------------------------------------
void KMFolderTree::slotFolderCollapsed( TQListViewItem * item )
{
  slotResetFolderList( item, false );
  KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);
  if ( !fti || !fti->folder() || !fti->folder()->storage() ) return;

  fti->setFolderSize( fti->folder()->storage()->folderSize() );
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotRenameFolder(TQListViewItem *item, int col,
                const TQString &text)
{

  KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>(item);

  if ((!fti) || (fti && fti->folder() && col != 0 && !currentFolder()->child()))
          return;

  TQString fldName, oldFldName;

  oldFldName = fti->name(0);

  if (!text.isEmpty())
          fldName = text;
  else
          fldName = oldFldName;

  fldName.replace("/", "");
  fldName.replace(TQRegExp("^\\."), "");

  if (fldName.isEmpty())
          fldName = i18n("unnamed");

  fti->setText(0, fldName);
  fti->folder()->rename(fldName, &(kmkernel->folderMgr()->dir()));
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotUpdateCountsDelayed(KMFolder * folder)
{
//  kdDebug(5006) << "KMFolderTree::slotUpdateCountsDelayed()" << endl;
  if ( !mFolderToUpdateCount.contains( folder->idString() ) )
  {
//    kdDebug( 5006 )<< "adding " << folder->idString() << " to updateCountList " << endl;
    mFolderToUpdateCount.insert( folder->idString(),folder );
  }
  if ( !mUpdateCountTimer->isActive() )
    mUpdateCountTimer->start( 500 );
}


void KMFolderTree::slotUpdateCountTimeout()
{
//  kdDebug(5006) << "KMFolderTree::slotUpdateCountTimeout()" << endl;

  TQMap<TQString,KMFolder*>::iterator it;
  for ( it= mFolderToUpdateCount.begin();
      it!=mFolderToUpdateCount.end();
      ++it )
  {
    slotUpdateCounts( it.data() );
  }
  mFolderToUpdateCount.clear();
  mUpdateCountTimer->stop();

}

void KMFolderTree::updatePopup() const
{
   mPopup->setItemChecked( mUnreadPop, isUnreadActive() );
   mPopup->setItemChecked( mTotalPop, isTotalActive() );
   mPopup->setItemChecked( mSizePop, isSizeActive() );
}

//-----------------------------------------------------------------------------
void KMFolderTree::toggleColumn(int column, bool openFolders)
{
  if (column == unread)
  {
    // switch unread
    if ( isUnreadActive() )
    {
      removeUnreadColumn();
      reload();
    } else {
      addUnreadColumn( i18n("Unread"), 70 );
      reload();
    }
    // toggle TDEPopupMenu
    mPopup->setItemChecked( mUnreadPop, isUnreadActive() );

  } else if (column == total) {
    // switch total
    if ( isTotalActive() )
    {
      removeTotalColumn();
      reload();
    } else {
      addTotalColumn( i18n("Total"), 70 );
      reload(openFolders);
    }
    mPopup->setItemChecked( mTotalPop, isTotalActive() );
  } else if (column == foldersize) {
    // switch total
    if ( isSizeActive() )
    {
      removeSizeColumn();
      reload();
    } else {
      addSizeColumn( i18n("Size"), 70 );
      reload( openFolders );
    }
    // toggle TDEPopupMenu
    mPopup->setItemChecked( mSizePop, isSizeActive() );

  } else kdDebug(5006) << "unknown column:" << column << endl;

  // toggles the switches of the mainwin
  emit columnsChanged();
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotToggleUnreadColumn()
{
  toggleColumn(unread);
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotToggleTotalColumn()
{
  // activate the total-column and force the folders to be opened
  toggleColumn(total, true);
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotToggleSizeColumn()
{
  // activate the size-column and force the folders to be opened
  toggleColumn(foldersize, true);
}


//-----------------------------------------------------------------------------
bool KMFolderTree::eventFilter( TQObject *o, TQEvent *e )
{
  if ( e->type() == TQEvent::MouseButtonPress &&
      TQT_TQMOUSEEVENT(e)->button() == Qt::RightButton &&
      o->isA(TQHEADER_OBJECT_NAME_STRING) )
  {
    mPopup->popup( TQT_TQMOUSEEVENT(e)->globalPos() );
    return true;
  }
  return KFolderTree::eventFilter(o, e);
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotCheckMail()
{
  if (!currentItem())
    return;
  KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>(currentItem());
  KMFolder* folder = fti->folder();
  if (folder && folder->storage() ) {
      if ( KMAccount* acct = folder->storage()->account() ) {
         kmkernel->acctMgr()->singleCheckMail(acct, true);
      }
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotNewMessageToMailingList()
{
  KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( currentItem() );
  if ( !fti || !fti->folder() )
    return;
  KMCommand *command = new KMMailingListPostCommand( this, fti->folder() );
  command->start();
}

//-----------------------------------------------------------------------------
void KMFolderTree::createFolderList( TQStringList *str,
                                     TQValueList<TQGuardedPtr<KMFolder> > *folders,
                                     bool localFolders,
                                     bool imapFolders,
                                     bool dimapFolders,
                                     bool searchFolders,
                                     bool includeNoContent,
                                     bool includeNoChildren )
{
  for ( TQListViewItemIterator it( this ) ; it.current() ; ++it )
  {
    KMFolderTreeItem * fti = static_cast<KMFolderTreeItem*>(it.current());
    if (!fti || !fti->folder()) continue;
    // type checks
    KMFolder* folder = fti->folder();
    if (!imapFolders && folder->folderType() == KMFolderTypeImap) continue;
    if (!dimapFolders && folder->folderType() == KMFolderTypeCachedImap) continue;
    if (!localFolders && (folder->folderType() == KMFolderTypeMbox ||
                          folder->folderType() == KMFolderTypeMaildir)) continue;
    if (!searchFolders && folder->folderType() == KMFolderTypeSearch) continue;
    if (!includeNoContent && folder->noContent()) continue;
    if (!includeNoChildren && folder->noChildren()) continue;
    TQString prefix;
    prefix.fill( ' ', 2 * fti->depth() );
    str->append(prefix + fti->text(0));
    folders->append(fti->folder());
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::slotResetFolderList( TQListViewItem* item, bool startList )
{
  if ( !item )
    item = currentItem();

  KMFolderTreeItem* fti = dynamic_cast<KMFolderTreeItem*>( item );
  if ( fti && fti->folder() &&
       fti->folder()->folderType() == KMFolderTypeImap )
  {
    KMFolderImap *folder = static_cast<KMFolderImap*>( fti->folder()->storage() );
    folder->setSubfolderState( KMFolderImap::imapNoInformation );
    if ( startList )
      folder->listDirectory();
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::showFolder( KMFolder* folder )
{
  if ( !folder ) return;
  TQListViewItem* item = indexOfFolder( folder );
  if ( item )
  {
    doFolderSelected( item );
    ensureItemVisible( item );
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::folderToPopupMenu( MenuAction action, TQObject *receiver,
    KMMenuToFolder *aMenuToFolder, TQPopupMenu *menu, TQListViewItem *item )
{
  while ( menu->count() )
  {
    TQPopupMenu *popup = menu->findItem( menu->idAt( 0 ) )->popup();
    if ( popup )
      delete popup;
    else
      menu->removeItemAt( 0 );
  }
  // connect the signals
  if ( action == MoveMessage || action == MoveFolder )
  {
    disconnect( menu, TQT_SIGNAL(activated(int)), receiver,
        TQT_SLOT(moveSelectedToFolder(int)) );
    connect( menu, TQT_SIGNAL(activated(int)), receiver,
        TQT_SLOT(moveSelectedToFolder(int)) );
  } else {
    disconnect( menu, TQT_SIGNAL(activated(int)), receiver,
        TQT_SLOT(copySelectedToFolder(int)) );
    connect( menu, TQT_SIGNAL(activated(int)), receiver,
        TQT_SLOT(copySelectedToFolder(int)) );
  }
  if ( !item ) {
    item = firstChild();

    // avoid a popup menu with the single entry 'Local Folders' if there
    // are no IMAP accounts
    if ( childCount() == 2 && action != MoveFolder ) { // only 'Local Folders' and 'Searches'
      KMFolderTreeItem *fti = static_cast<KMFolderTreeItem*>( item );
      if ( fti->protocol() == KFolderTreeItem::Search ) {
        // skip 'Searches'
        item = item->nextSibling();
        fti = static_cast<KMFolderTreeItem*>( item );
      }
      folderToPopupMenu( action, receiver, aMenuToFolder, menu, fti->firstChild() );
      return;
    }
  }

  while ( item )
  {
    KMFolderTreeItem* fti = static_cast<KMFolderTreeItem*>( item );
    if ( fti->protocol() == KFolderTreeItem::Search )
    {
      // skip search folders
      item = item->nextSibling();
      continue;
    }
    TQString label = fti->text( 0 );
    label.replace( "&","&&" );
    if ( fti->firstChild() )
    {
      // new level
      TQPopupMenu* popup = new TQPopupMenu( menu, "subMenu" );
      folderToPopupMenu( action, receiver, aMenuToFolder, popup, fti->firstChild() );
      bool subMenu = false;
      if ( ( action == MoveMessage || action == CopyMessage ) &&
           fti->folder() && !fti->folder()->noContent() )
        subMenu = true;
      if ( ( action == MoveFolder || action == CopyFolder )
          && ( !fti->folder() || ( fti->folder() && !fti->folder()->noChildren() ) ) )
        subMenu = true;

      TQString sourceFolderName;
      KMFolderTreeItem* srcItem = dynamic_cast<KMFolderTreeItem*>( currentItem() );
      if ( srcItem )
        sourceFolderName = srcItem->text( 0 );

      if ( (action == MoveFolder || action == CopyFolder)
              && fti->folder() && fti->folder()->child()
              && fti->folder()->child()->hasNamedFolder( sourceFolderName ) ) {
        subMenu = false;
      }

      if ( subMenu )
      {
        int menuId;
        if ( action == MoveMessage || action == MoveFolder )
          menuId = popup->insertItem( i18n("Move to This Folder"), -1, 0 );
        else
          menuId = popup->insertItem( i18n("Copy to This Folder"), -1, 0 );
        popup->insertSeparator( 1 );
        aMenuToFolder->insert( menuId, fti->folder() );
      }
      menu->insertItem( label, popup );
    } else
    {
      // insert an item
      int menuId = menu->insertItem( label );
      if ( fti->folder() )
        aMenuToFolder->insert( menuId, fti->folder() );
      bool enabled = (fti->folder() ? true : false);
      if ( fti->folder() &&
           ( fti->folder()->isReadOnly() || fti->folder()->noContent() ) )
        enabled = false;
      menu->setItemEnabled( menuId, enabled );
    }

    item = item->nextSibling();
  }
}

//-----------------------------------------------------------------------------
void KMFolderTree::moveSelectedToFolder( int menuId )
{
  moveOrCopyFolder( selectedFolders(), mMenuToFolder[ menuId ], true /*move*/ );
}

//-----------------------------------------------------------------------------
void KMFolderTree::copySelectedToFolder( int menuId )
{
  moveOrCopyFolder( selectedFolders(), mMenuToFolder[ menuId ], false /*copy, don't move*/ );
}

//-----------------------------------------------------------------------------
void KMFolderTree::moveOrCopyFolder( TQValueList<TQGuardedPtr<KMFolder> > sources, KMFolder* destination, bool move )
{
  kdDebug(5006) << k_funcinfo << "source: " << sources << " destination: " << destination << " move: " << move << endl;

  // Disable drag during copy operation since it prevents from many crashes
  setDragEnabled( false );

  KMFolderDir* parent = &(kmkernel->folderMgr()->dir());
  if ( destination )
    parent = destination->createChildFolder();

  TQStringList sourceFolderNames;

  // check if move/copy is possible at all
  for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); it != sources.constEnd(); ++it ) {
    KMFolder* source = *it;

    // check if folder with same name already exits
    TQString sourceFolderName;
    if ( source )
      sourceFolderName = source->label();

    if ( parent->hasNamedFolder( sourceFolderName ) || sourceFolderNames.contains( sourceFolderName ) ) {
      KMessageBox::error( this, i18n("<qt>Cannot move or copy folder <b>%1</b> here because a folder with the same name already exists.</qt>")
          .arg( sourceFolderName ) );
      setDragEnabled( true );
      return;
    }
    sourceFolderNames.append( sourceFolderName );

    // don't move/copy a folder that's still not completely moved/copied
    KMFolder *f = source;
    while ( f ) {
      if ( f->moveInProgress() ) {
        KMessageBox::error( this, i18n("<qt>Cannot move or copy folder <b>%1</b> because it is not completely copied itself.</qt>")
            .arg( sourceFolderName ) );
        setDragEnabled( true );
        return;
      }
      if ( f->parent() )
        f = f->parent()->owner();
    }

    TQString message =
      i18n( "<qt>Cannot move or copy folder <b>%1</b> into a subfolder below itself.</qt>" ).
          arg( sourceFolderName );
    KMFolderDir* folderDir = parent;
    // check that the folder can be moved
    if ( source && source->child() )
    {
      while ( folderDir && ( folderDir != &kmkernel->folderMgr()->dir() ) &&
          ( folderDir != source->parent() ) )
      {
        if ( folderDir->findRef( source ) != -1 )
        {
          KMessageBox::error( this, message );
          setDragEnabled( true );
          return;
        }
        folderDir = folderDir->parent();
      }
    }

    if( source && source->child() && parent &&
        ( parent->path().find( source->child()->path() + "/" ) == 0 ) ) {
      KMessageBox::error( this, message );
      setDragEnabled( true );
      return;
    }

    if( source && source->child()
        && ( parent == source->child() ) ) {
      KMessageBox::error( this, message );
      setDragEnabled( true );
      return;
    }
  }

  // check if the source folders are independent of each other
  for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); move && it != sources.constEnd(); ++it ) {
    KMFolderDir *parentDir = (*it)->child();
    if ( !parentDir )
      continue;
    for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it2 = sources.constBegin(); it2 != sources.constEnd(); ++it2 ) {
      if ( *it == *it2 )
        continue;
      KMFolderDir *childDir = (*it2)->parent();
      do {
        if ( parentDir == childDir || parentDir->findRef( childDir->owner() ) != -1 ) {
          KMessageBox::error( this, i18n("Moving the selected folders is not possible") );
          setDragEnabled( true );
          return;
        }
        childDir = childDir->parent();
      }
      while ( childDir && childDir != &kmkernel->folderMgr()->dir() );
    }
  }

  // de-select moved source folders (can cause crash due to unGetMsg() in KMHeaders)
  if ( move ) {
    doFolderSelected( indexOfFolder( destination ), false );
    oldCurrent = currentItem();
  }

  // do the actual move/copy
  for ( TQValueList<TQGuardedPtr<KMFolder> >::ConstIterator it = sources.constBegin(); it != sources.constEnd(); ++it ) {
    KMFolder* source = *it;
    if ( move ) {
      kdDebug(5006) << "move folder " << (source ? source->label(): "Unknown") << " to "
        << ( destination ? destination->label() : "Local Folders" ) << endl;
      kmkernel->folderMgr()->moveFolder( source, parent );
    } else {
      kmkernel->folderMgr()->copyFolder( source, parent );
    }
  }
}

TQDragObject * KMFolderTree::dragObject()
{
  KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>
      (itemAt(viewport()->mapFromGlobal(TQCursor::pos())));
  if ( !item || !item->parent() || !item->folder() ) // top-level items or something invalid
    return 0;
  mCopySourceFolders = selectedFolders();

  TQDragObject *drag = KFolderTree::dragObject();
  if ( drag )
    drag->setPixmap( SmallIcon("folder") );
  return drag;
}

void KMFolderTree::copyFolder()
{
  KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() );
  if ( item ) {
    mCopySourceFolders = selectedFolders();
    mCutFolder = false;
  }
  updateCopyActions();
}

void KMFolderTree::cutFolder()
{
  KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() );
  if ( item ) {
    mCopySourceFolders = selectedFolders();
    mCutFolder = true;
  }
  updateCopyActions();
}

void KMFolderTree::pasteFolder()
{
  KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() );
  if ( !mCopySourceFolders.isEmpty() && item && !mCopySourceFolders.contains( item->folder() ) ) {
    moveOrCopyFolder( mCopySourceFolders, item->folder(), mCutFolder );
    if ( mCutFolder )
      mCopySourceFolders.clear();
  }
  updateCopyActions();
}

void KMFolderTree::updateCopyActions()
{
  TDEAction *copy = mMainWidget->action("copy_folder");
  TDEAction *cut = mMainWidget->action("cut_folder");
  TDEAction *paste = mMainWidget->action("paste_folder");
  KMFolderTreeItem *item = static_cast<KMFolderTreeItem*>( currentItem() );

  if ( !item ||  !item->folder() ) {
    copy->setEnabled( false );
    cut->setEnabled( false );
  } else {
    copy->setEnabled( true );
    cut->setEnabled( item->folder()->isMoveable() );
  }

  if ( mCopySourceFolders.isEmpty() )
    paste->setEnabled( false );
  else
    paste->setEnabled( true );
}

void KMFolderTree::slotSyncStateChanged()
{
  // Only emit the signal when a selected folder changes, otherwise the folder menu is updated
  // too often
  TQValueList< TQGuardedPtr<KMFolder> > folders = selectedFolders();
  TQValueList< TQGuardedPtr<KMFolder> >::const_iterator it = folders.constBegin();
  TQValueList< TQGuardedPtr<KMFolder> >::const_iterator end = folders.constEnd();
  while ( it != end ) {
    TQGuardedPtr<KMFolder> folder = *it;
    if ( folder == sender() ) {
      emit syncStateChanged();
      break;
    }
    ++it;
  }
}

void KMFolderTree::slotAddToFavorites()
{
  KMail::FavoriteFolderView *favView = mMainWidget->favoriteFolderView();
  assert( favView );
  for ( TQListViewItemIterator it( this ); it.current(); ++it ) {
    if ( it.current()->isSelected() )
      favView->addFolder( static_cast<KMFolderTreeItem*>( it.current() ) );
  }
}

void KMFolderTree::slotUnhideLocalInbox()
{
  disconnect( kmkernel->inboxFolder(), TQT_SIGNAL(msgAdded(KMFolder*,TQ_UINT32)),
              this, TQT_SLOT(slotUnhideLocalInbox()) );
  reload();
}

void KMFolderTree::delayedReload()
{
  TQTimer::singleShot( 0, this, TQT_SLOT(reload()) );
}

#include "kmfoldertree.moc"
