/***************************************************************************
 *   Copyright (C) 2005-2007 by Rajko Albrecht                             *
 *   ral@alwins-world.de                                                   *
 *                                                                         *
 *   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; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include "tdesvnfilelist.h"
#include "tdesvn_part.h"
#include "filelistviewitem.h"
#include "importdir_logmsg.h"
#include "copymoveview_impl.h"
#include "mergedlg_impl.h"
#include "svnactions.h"
#include "svnfiletip.h"
#include "keystatus.h"
#include "opencontextmenu.h"
#include "checkoutinfo_impl.h"
#include "stopdlg.h"
#include "tdesvnsettings.h"
#include "revision.h"
#include "dirent.h"
#include "client.h"
#include "status.h"
#include "url.h"
#include "sshagent.h"
#include "sub2qt.h"
#include "cursorstack.h"
#include "widgetblockstack.h"

#include <tdeapplication.h>
#include <kiconloader.h>
#include <kdirwatch.h>
#include <tdelocale.h>
#include <tdeactioncollection.h>
#include <tdeshortcut.h>
#include <tdemessagebox.h>
#include <kdirselectdialog.h>
#include <klineedit.h>
#include <tdefileitem.h>
#include <kdialog.h>
#include <tdefiledialog.h>
#include <kdebug.h>
#include <kurldrag.h>
#include <tdetempfile.h>
#include <tdeio/job.h>
#include <krun.h>
#include <kurldrag.h>
#include <ktrader.h>

#include <tqvbox.h>
#include <tqpainter.h>
#include <tqstyle.h>
#include <tqapplication.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqtooltip.h>
#include <tqregexp.h>
#include <tqpopupmenu.h>
#include <tqcursor.h>
#include <tqheader.h>
#include <tqcheckbox.h>

#include <unistd.h>

class KdesvnFileListPrivate{
public:
    KdesvnFileListPrivate();
    virtual ~KdesvnFileListPrivate()
    {
        if (m_DirWatch) {
            m_DirWatch->stopScan();
            delete m_DirWatch;
        }
        delete m_fileTip;
        kdDebug()<<"Destructor KdesvnFileListPrivate done"<<endl;
    };
    TQListViewItem *dragOverItem;
    TQPoint dragOverPoint;
    TQRect mOldDropHighlighter;
    svn::Revision m_remoteRevision;
    KDirWatch*m_DirWatch;
    SvnFileTip*m_fileTip;
    int mlist_icon_size;
    bool mdisp_ignored_files;
    bool mdisp_unknown_files;
    bool mdisp_overlay;
    /* returns true if the display must refreshed */
    bool reReadSettings();

    bool intern_dropRunning;
    KURL::List intern_drops;
    TQString intern_drop_target,merge_Src1, merge_Src2,merge_Target;
    TQDropEvent::Action intern_drop_action;
    TQPoint intern_drop_pos;
    TQTimer drop_timer;
    TQTimer dirwatch_timer;
    TQTimer propTimer;

    bool mousePressed;
    TQPoint presspos;

    TQMap<TQString,TQChar> dirItems;

    void stopDirTimer()
    {
        dirwatch_timer.stop();
    }

    void startDirTimer()
    {
        dirwatch_timer.start(250,true);
    }

    void connectDirTimer(TQObject*ob)
    {
        TQObject::connect(&dirwatch_timer,TQT_SIGNAL(timeout()),ob,TQT_SLOT(_dirwatchTimeout()));
    }
    void stopScan()
    {
        if (m_DirWatch) {
            m_DirWatch->stopScan();
        }
    }
    void startScan()
    {
        if (m_DirWatch) {
            m_DirWatch->startScan();
        }
    }
    void startProptimer()
    {
        propTimer.start(100,true);
    }
    void stopProptimer()
    {
        propTimer.stop();
    }
    void connectPropTimer(TQObject*ob)
    {
        TQObject::connect(&propTimer,TQT_SIGNAL(timeout()),ob,TQT_SLOT(_propListTimeout()));
    }

private:
    void readSettings();
};

KdesvnFileListPrivate::KdesvnFileListPrivate()
    : dragOverItem(0),dragOverPoint(TQPoint(0,0)),mOldDropHighlighter()
{
    m_remoteRevision = svn::Revision::HEAD;
    m_DirWatch = 0;
    intern_dropRunning=false;
    mousePressed = false;
    readSettings();
}

void KdesvnFileListPrivate::readSettings()
{
    mlist_icon_size = Kdesvnsettings::listview_icon_size();
    mdisp_ignored_files = Kdesvnsettings::display_ignored_files();
    mdisp_unknown_files = Kdesvnsettings::display_unknown_files();
    mdisp_overlay = Kdesvnsettings::display_overlays();
}

bool KdesvnFileListPrivate::reReadSettings()
{
    int _size = mlist_icon_size;
    bool _ignored = mdisp_ignored_files;
    bool _overlay = mdisp_overlay;
    bool _unknown = mdisp_unknown_files;
    readSettings();
    return (_size != mlist_icon_size||
            _ignored!=mdisp_ignored_files||
            _overlay!=mdisp_overlay||
            _unknown != mdisp_unknown_files);
}

tdesvnfilelist::tdesvnfilelist(TDEActionCollection*aCollect,TQWidget *parent, const char *name)
 : TDEListView(parent, name),ItemDisplay(),m_SvnWrapper(new SvnActions(this))
{
    m_SelectedItems = 0;
    m_pList = new KdesvnFileListPrivate;
    m_filesAction = aCollect;
    m_pList->m_fileTip=new SvnFileTip(this);
    m_pList->m_fileTip->setOptions(Kdesvnsettings::display_file_tips()&&
        TQToolTip::isGloballyEnabled(),true,6);

    SshAgent ssh;
    ssh.querySshAgent();

    setMultiSelection(true);
    setSelectionModeExt(FileManager);
    setShowSortIndicator(true);
    setAllColumnsShowFocus (true);
    setRootIsDecorated(true);
    addColumn(i18n("Name"));
    addColumn(i18n("Status"));
    addColumn(i18n("Last changed Revision"));
    addColumn(i18n("Last author"));
    addColumn(i18n("Last change date"));
    addColumn(i18n("Locked by"));
    setSortColumn(FileListViewItem::COL_NAME);
    setupActions();

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

    /* not via executed 'cause click may used for selection - single click execution
       just confuses in an application */
    connect(this,TQT_SIGNAL(doubleClicked(TQListViewItem*)),this,TQT_SLOT(slotItemDoubleClicked(TQListViewItem*)));
    connect(this,TQT_SIGNAL(returnPressed(TQListViewItem*)),this,TQT_SLOT(slotItemDoubleClicked(TQListViewItem*)));

    connect(this,TQT_SIGNAL(selectionChanged()),this,TQT_SLOT(slotSelectionChanged()));
    connect(m_SvnWrapper,TQT_SIGNAL(clientException(const TQString&)),this,TQT_SLOT(slotClientException(const TQString&)));
    connect(m_SvnWrapper,TQT_SIGNAL(sendNotify(const TQString&)),this,TQT_SLOT(slotNotifyMessage(const TQString&)));
    connect(m_SvnWrapper,TQT_SIGNAL(reinitItem(SvnItem*)),this,TQT_SLOT(slotReinitItem(SvnItem*)));
    connect(m_SvnWrapper,TQT_SIGNAL(sigRefreshAll()),this,TQT_SLOT(refreshCurrentTree()));
    connect(m_SvnWrapper,TQT_SIGNAL(sigRefreshCurrent(SvnItem*)),this,TQT_SLOT(refreshCurrent(SvnItem*)));
    connect(m_SvnWrapper,TQT_SIGNAL(sigRefreshIcons(bool)),this,TQT_SLOT(slotRescanIcons(bool)));
    connect(this,TQT_SIGNAL(dropped (TQDropEvent*,TQListViewItem*)),
            this,TQT_SLOT(slotDropped(TQDropEvent*,TQListViewItem*)));
    connect(m_SvnWrapper,TQT_SIGNAL(sigGotourl(const TQString&)),this,TQT_SLOT(_openURL(const TQString&)));

    connect(m_SvnWrapper,TQT_SIGNAL(sigCacheStatus(TQ_LONG,TQ_LONG)),this,TQT_SIGNAL(sigCacheStatus(TQ_LONG,TQ_LONG)));
    connect(m_SvnWrapper,TQT_SIGNAL(sigThreadsChanged()),this,TQT_SLOT(enableActions()));

    m_pList->connectDirTimer(TQT_TQOBJECT(this));
    m_pList->connectPropTimer(TQT_TQOBJECT(this));

    setDropHighlighter(true);
    setDragEnabled(true);
    setItemsMovable(true);
    setDropVisualizer(false);
    setAcceptDrops(true);
}

svn::Client*tdesvnfilelist::svnclient()
{
    return m_SvnWrapper->svnclient();
}

void tdesvnfilelist::setupActions()
{
    if (!m_filesAction) return;
    TDEAction*tmp_action;
    /* local and remote actions */
    /* 1. actions on dirs AND files */
    //new TDEAction(i18n("Log..."),"tdesvnlog",TDEShortcut(SHIFT+CTRL+Key_L),this,TQT_SLOT(slotMakeRangeLog()),m_filesAction,"make_svn_log");
    new TDEAction(i18n("Full Log"),"tdesvnlog",TDEShortcut(CTRL+Key_L),TQT_TQOBJECT(this),TQT_SLOT(slotMakeLog()),m_filesAction,"make_svn_log_full");
    new TDEAction(i18n("Full revision tree"),"tdesvnlog",TDEShortcut(CTRL+Key_T),TQT_TQOBJECT(this),TQT_SLOT(slotMakeTree()),m_filesAction,"make_svn_tree");
    new TDEAction(i18n("Partial revision tree"),"tdesvnlog",TDEShortcut(SHIFT+CTRL+Key_T),
        TQT_TQOBJECT(this),TQT_SLOT(slotMakePartTree()),m_filesAction,"make_svn_partialtree");

    new TDEAction(i18n("Properties"),"edit",
        TDEShortcut(CTRL+Key_P),m_SvnWrapper,TQT_SLOT(slotProperties()),m_filesAction,"make_svn_property");
    new TDEAction(i18n("Display Properties"),"edit",
        TDEShortcut(SHIFT+CTRL+Key_P),TQT_TQOBJECT(this),TQT_SLOT(slotDisplayProperties()),m_filesAction,"get_svn_property");

    tmp_action = new TDEAction(i18n("Display last changes"),"tdesvndiff",
                TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotDisplayLastDiff()),m_filesAction,"make_last_change");
    tmp_action->setToolTip(i18n("Display last changes as difference to previous commit."));

    m_InfoAction = new TDEAction(i18n("Details"),"tdesvninfo",
        TDEShortcut(CTRL+Key_I),TQT_TQOBJECT(this),TQT_SLOT(slotInfo()),m_filesAction,"make_svn_info");
    m_RenameAction = new TDEAction(i18n("Move"),"move",
        TDEShortcut(Key_F2),TQT_TQOBJECT(this),TQT_SLOT(slotRename()),m_filesAction,"make_svn_rename");
    m_CopyAction = new TDEAction(i18n("Copy"),"tdesvncopy",
        TDEShortcut(CTRL+Key_C),TQT_TQOBJECT(this),TQT_SLOT(slotCopy()),m_filesAction,"make_svn_copy");
    tmp_action = new TDEAction(i18n("Check for updates"),"tdesvncheckupdates",TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotCheckUpdates()),m_filesAction,"make_check_updates");
    tmp_action->setToolTip(i18n("Check if current working copy has items with newer version in repository"));

    /* 2. actions only on files */
    m_BlameAction = new TDEAction(i18n("Blame"),"tdesvnblame",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotBlame()),m_filesAction,"make_svn_blame");
    m_BlameAction->setToolTip(i18n("Output the content of specified files or URLs with revision and author information in-line."));
    m_BlameRangeAction = new TDEAction(i18n("Blame range"),"tdesvnblame",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotRangeBlame()),m_filesAction,"make_svn_range_blame");
    m_BlameRangeAction->setToolTip(i18n("Output the content of specified files or URLs with revision and author information in-line."));
    m_CatAction = new TDEAction(i18n("Cat head"), "tdesvncat",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotCat()),m_filesAction,"make_svn_cat");
    m_CatAction->setToolTip(i18n("Output the content of specified files or URLs."));
    tmp_action = new TDEAction(i18n("Cat revision..."),"tdesvncat",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotRevisionCat()),m_filesAction,"make_revisions_cat");
    tmp_action->setToolTip(i18n("Output the content of specified files or URLs at specific revision."));

    m_LockAction = new TDEAction(i18n("Lock current items"),"tdesvnlock",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotLock()),m_filesAction,"make_svn_lock");
    m_UnlockAction = new TDEAction(i18n("Unlock current items"),"tdesvnunlock",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotUnlock()),m_filesAction,"make_svn_unlock");

    /* 3. actions only on dirs */
    m_MkdirAction = new TDEAction(i18n("New folder"),"folder-new",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotMkdir()),m_filesAction,"make_svn_mkdir");
    m_switchRepository = new TDEAction(i18n("Switch repository"),"tdesvnswitch",
        TDEShortcut(), m_SvnWrapper,TQT_SLOT(slotSwitch()),m_filesAction,"make_svn_switch");
    m_switchRepository->setToolTip(i18n("Switch repository path of current working copy path (\"svn switch\")"));
    tmp_action = new TDEAction(i18n("Relocate current working copy url"),"tdesvnrelocate",TDEShortcut(),
        TQT_TQOBJECT(this),TQT_SLOT(slotRelocate()),m_filesAction,"make_svn_relocate");
    tmp_action->setToolTip(i18n("Relocate url of current working copy path to other url"));
    tmp_action = new TDEAction(i18n("Check for unversioned items"),"tdesvnaddrecursive",TDEShortcut(),
        TQT_TQOBJECT(this),TQT_SLOT(slotCheckNewItems()),m_filesAction,"make_check_unversioned");
    tmp_action->setToolTip(i18n("Browse folder for unversioned items and add them if wanted."));

    m_changeToRepository = new TDEAction(i18n("Open repository of working copy"),"go-home",TDEShortcut(),
        TQT_TQOBJECT(this),TQT_SLOT(slotChangeToRepository()),m_filesAction,"make_switch_to_repo");
    m_changeToRepository->setToolTip(i18n("Opens the repository the current working copy was checked out from"));

    m_CleanupAction = new TDEAction(i18n("Cleanup"),"tdesvncleanup",
	TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotCleanupAction()),m_filesAction,"make_cleanup");
    m_CleanupAction->setToolTip(i18n("Recursively clean up the working copy, removing locks, resuming unfinished operations, etc."));
    m_ImportDirsIntoCurrent  = new TDEAction(i18n("Import folders into current"),"fileimport",TDEShortcut(),
        TQT_TQOBJECT(this),TQT_SLOT(slotImportDirsIntoCurrent()),m_filesAction,"make_import_dirs_into_current");
    m_ImportDirsIntoCurrent->setToolTip(i18n("Import folder content into current url"));

    /* local only actions */
    /* 1. actions on files AND dirs*/
    m_AddCurrent = new TDEAction(i18n("Add selected files/dirs"),
        "tdesvnadd",TDEShortcut(Key_Insert),m_SvnWrapper,TQT_SLOT(slotAdd()),m_filesAction,"make_svn_add");
    m_AddCurrent->setToolTip(i18n("Adding selected files and/or directories to repository"));
    tmp_action = new TDEAction("Add selected files/dirs recursive",
        "tdesvnaddrecursive",TDEShortcut(CTRL+Key_Insert),m_SvnWrapper,TQT_SLOT(slotAddRec()),m_filesAction,"make_svn_addrec");
    tmp_action->setToolTip(i18n("Adding selected files and/or directories to repository and all subitems of folders"));

    m_DelCurrent = new TDEAction(i18n("Delete selected files/dirs"),"tdesvndelete",
        TDEShortcut(Key_Delete),TQT_TQOBJECT(this),TQT_SLOT(slotDelete()),m_filesAction,"make_svn_remove");
    m_DelCurrent->setToolTip(i18n("Deleting selected files and/or directories from repository"));
    m_RevertAction  = new TDEAction(i18n("Revert current changes"),"document-revert",
        TDEShortcut(),m_SvnWrapper,TQT_SLOT(slotRevert()),m_filesAction,"make_svn_revert");

    m_ResolvedAction = new TDEAction(i18n("Mark resolved"),TDEShortcut(),
        TQT_TQOBJECT(this),TQT_SLOT(slotResolved()),m_filesAction,"make_resolved");
    m_ResolvedAction->setToolTip(i18n("Marking files or dirs resolved"));

    tmp_action = new TDEAction(i18n("Resolve conflicts"),TDEShortcut(),
                             TQT_TQOBJECT(this),TQT_SLOT(slotTryResolve()),m_filesAction,"make_try_resolve");

    m_IgnoreAction = new TDEAction(i18n("Ignore/Unignore current item"),TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotIgnore()),m_filesAction,"make_svn_ignore");

    m_UpdateHead = new TDEAction(i18n("Update to head"),"tdesvnupdate",
        TDEShortcut(),m_SvnWrapper,TQT_SLOT(slotUpdateHeadRec()),m_filesAction,"make_svn_headupdate");
    m_UpdateRev = new TDEAction(i18n("Update to revision..."),"tdesvnupdate",
        TDEShortcut(),m_SvnWrapper,TQT_SLOT(slotUpdateTo()),m_filesAction,"make_svn_revupdate");
    m_commitAction = new TDEAction(i18n("Commit"),"tdesvncommit",
        TDEShortcut("CTRL+#"),m_SvnWrapper,TQT_SLOT(slotCommit()),m_filesAction,"make_svn_commit");

    tmp_action = new TDEAction(i18n("Diff local changes"),"tdesvndiff",
        TDEShortcut(CTRL+Key_D),TQT_TQOBJECT(this),TQT_SLOT(slotSimpleBaseDiff()),m_filesAction,"make_svn_basediff");
    tmp_action->setToolTip(i18n("Diff working copy against BASE (last checked out version) - doesn't require access to repository"));

    tmp_action = new TDEAction(i18n("Diff against HEAD"),"tdesvndiff",
        TDEShortcut(CTRL+Key_H),TQT_TQOBJECT(this),TQT_SLOT(slotSimpleHeadDiff()),m_filesAction,"make_svn_headdiff");
    tmp_action->setToolTip(i18n("Diff working copy against HEAD (last checked in version)- requires access to repository"));

    tmp_action = new TDEAction(i18n("Diff items"),"tdesvndiff",
                             TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotDiffPathes()),m_filesAction,"make_svn_itemsdiff");
    tmp_action->setToolTip(i18n("Diff two items"));


    m_MergeRevisionAction = new TDEAction(i18n("Merge two revisions"),"tdesvnmerge",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotMergeRevisions()),m_filesAction,"make_svn_merge_revisions");
    m_MergeRevisionAction->setToolTip(i18n("Merge two revisions of this entry into itself"));

    tmp_action=new TDEAction(i18n("Merge..."),"tdesvnmerge",
        TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotMerge()),m_filesAction,"make_svn_merge");
    tmp_action->setToolTip("Merge repository path into current worky copy path or current repository path into a target");
    tmp_action=new TDEAction( i18n( "Open With..." ), 0, TQT_TQOBJECT(this), TQT_SLOT( slotOpenWith() ), m_filesAction, "openwith" );

    /* remote actions only */
    m_CheckoutCurrentAction = new TDEAction(i18n("Checkout current repository path"),"tdesvncheckout",TDEShortcut(),
        m_SvnWrapper,TQT_SLOT(slotCheckoutCurrent()),m_filesAction,"make_svn_checkout_current");
    m_ExportCurrentAction = new TDEAction(i18n("Export current repository path"),"tdesvnexport",TDEShortcut(),
        m_SvnWrapper,TQT_SLOT(slotExportCurrent()),m_filesAction,"make_svn_export_current");
    new TDEAction(i18n("Select browse revision"),TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotSelectBrowsingRevision()),m_filesAction,"switch_browse_revision");

    /* independe actions */
    m_CheckoutAction = new TDEAction(i18n("Checkout a repository"),"tdesvncheckout",
        TDEShortcut(),m_SvnWrapper,TQT_SLOT(slotCheckout()),m_filesAction,"make_svn_checkout");
    m_ExportAction = new TDEAction(i18n("Export a repository"),"tdesvnexport",
        TDEShortcut(),m_SvnWrapper,TQT_SLOT(slotExport()),m_filesAction,"make_svn_export");
    m_RefreshViewAction = new TDEAction(i18n("Refresh view"),"reload",TDEShortcut(Key_F5),TQT_TQOBJECT(this),TQT_SLOT(refreshCurrentTree()),m_filesAction,"make_view_refresh");

    new TDEAction(i18n("Diff revisions"),"tdesvndiff",TDEShortcut(),TQT_TQOBJECT(this),TQT_SLOT(slotDiffRevisions()),m_filesAction,"make_revisions_diff");

    /* folding options */
    tmp_action = new TDEAction( i18n("Unfold File Tree"), 0, TQT_TQOBJECT(this) , TQT_SLOT(slotUnfoldTree()), m_filesAction, "view_unfold_tree" );
    tmp_action->setToolTip(i18n("Opens all branches of the file tree"));
    tmp_action = new TDEAction( i18n("Fold File Tree"), 0, TQT_TQOBJECT(this), TQT_SLOT(slotFoldTree()), m_filesAction, "view_fold_tree" );
    tmp_action->setToolTip(i18n("Closes all branches of the file tree"));

    /* caching */
    tmp_action = new TDEAction( i18n("Update log cache"),0,TQT_TQOBJECT(this),TQT_SLOT(slotUpdateLogCache()),m_filesAction,"update_log_cache" );
    tmp_action->setToolTip(i18n("Update the log cache for current repository"));
    /*    tmp_action = new TDEAction( i18n("Stop update log cache"),0,this,TQT_SLOT(slotUpdateLogCache()),m_filesAction,"stop_update_log_cache" );
        tmp_action->setToolTip(i18n("Stop the update of the log cache"));
    */

    enableActions();
    m_filesAction->setHighlightingEnabled(true);
}

TDEActionCollection*tdesvnfilelist::filesActions()
{
    return m_filesAction;
}

FileListViewItemList* tdesvnfilelist::allSelected()
{
    if (!m_SelectedItems) {
        m_SelectedItems = new FileListViewItemList;
    }
    return m_SelectedItems;
}

void tdesvnfilelist::SelectionList(SvnItemList*target)
{
    if (!m_SelectedItems||!target) return;
    FileListViewItemListIterator iter(*m_SelectedItems);
    FileListViewItem*cur;
    while ( (cur=iter.current())!=0) {
        ++iter;
        target->append(cur);
    }
}

SvnItem*tdesvnfilelist::SelectedOrMain()
{
    if (singleSelected()!=0) {
        return singleSelected();
    }
    if (isWorkingCopy()&&firstChild()) {
        return static_cast<FileListViewItem*>(firstChild());
    }
    return 0;
}

KURL::List tdesvnfilelist::selectedUrls()
{
    KURL::List lst;
    FileListViewItemList*ls = allSelected();
    FileListViewItemListIterator it(*ls);
    FileListViewItem*cur;
    while ( (cur=it.current())!=0) {
        ++it;
        /* for putting it to outside we must convert it to TDEIO urls */
        lst.append(cur->kdeName(m_pList->m_remoteRevision));
    }
    return lst;
}

TQWidget*tdesvnfilelist::realWidget()
{
    return this;
}

FileListViewItem* tdesvnfilelist::singleSelected()
{
    if (m_SelectedItems && m_SelectedItems->count()==1) {
        return m_SelectedItems->at(0);
    }
    return 0;
}

SvnItem*tdesvnfilelist::Selected()
{
    return singleSelected();
}

void tdesvnfilelist::_openURL(const TQString&url)
{
    openURL(url,true);
    emit sigUrlChanged(baseUri());
}

bool tdesvnfilelist::openURL( const KURL &url,bool noReinit )
{
    CursorStack a;
    m_SvnWrapper->killallThreads();
    clear();
    emit sigProplist(svn::PathPropertiesMapListPtr(new svn::PathPropertiesMapList()),false,TQString(""));
    m_Dirsread.clear();
    if (m_SelectedItems) {
        m_SelectedItems->clear();
    }
    m_LastException="";
    delete m_pList->m_DirWatch;
    m_pList->m_DirWatch=0;
    m_pList->dirItems.clear();
    m_pList->stopDirTimer();

    if (!noReinit) m_SvnWrapper->reInitClient();

    TQString query = url.query();

    KURL _url = url;
    TQString proto = svn::Url::transformProtokoll(url.protocol());
    _url.cleanPath(true);
    _url.setProtocol(proto);
    proto = _url.url(-1);

    TQStringList s = TQStringList::split("?",proto);
    if (s.size()>1) {
        setBaseUri(s[0]);
    } else {
        setBaseUri(proto);
    }
    setWorkingCopy(false);
    setNetworked(false);

    m_pList->m_remoteRevision=svn::Revision::HEAD;


    TQString _dummy;

    if (!TQString::compare("svn+file",url.protocol())) {
        setBaseUri("file://"+url.path());
    } else {
        if (url.isLocalFile()) {
            TQString s = url.path();
            while(s.endsWith("/")) {
                s.remove(s.length()-1,1);
            }
            TQFileInfo fi(s);
            if (fi.exists() && fi.isSymLink()) {
                TQString sl = fi.readLink();
                if (sl.startsWith("/")) {
                    setBaseUri(sl);
                } else {
                    fi.setFile(fi.dirPath()+"/"+sl);
                    setBaseUri(fi.absFilePath());
                }
            } else {
                setBaseUri(url.path());
            }
            if (m_SvnWrapper->isLocalWorkingCopy(baseUri(),_dummy)) {
                setWorkingCopy(true);
            } else {
                // yes! KURL sometimes makes a correct localfile url (file:///)
                // to a simple file:/ - that breakes subversion lib. so we make sure
                // that we have a correct url
                setBaseUri("file://"+baseUri());
            }
        } else {
            setNetworked(true);
            if (!Kdesvnsettings::network_on()) {
                setBaseUri("");
                setNetworked(false);
                clear();
                KMessageBox::error(this,i18n("Networked URL to open but networking is disabled!"));
                emit changeCaption("");
                emit sigUrlOpend(false);
                return false;
            }
        }
    }
    if (query.length()>1) {
        TQMap<TQString,TQString> q = url.queryItems();
        if (q.find("rev")!=q.end()) {
            TQString v = q["rev"];
            svn::Revision tmp;
            m_SvnWrapper->svnclient()->url2Revision(v,m_pList->m_remoteRevision,tmp);
            if (m_pList->m_remoteRevision==svn::Revision::UNDEFINED) {
                m_pList->m_remoteRevision = svn::Revision::HEAD;
            }
        }
    }

    if (url.protocol()=="svn+ssh"||
        url.protocol()=="ksvn+ssh") {
        SshAgent ssh;
        ssh.addSshIdentities();
    }
    m_SvnWrapper->clearUpdateCache();
    if (isWorkingCopy()) {
        m_pList->m_DirWatch=new KDirWatch(TQT_TQOBJECT(this));
        connect(m_pList->m_DirWatch,TQT_SIGNAL(dirty(const TQString&)),this,TQT_SLOT(slotDirItemDirty(const TQString&)));
        connect(m_pList->m_DirWatch,TQT_SIGNAL(created(const TQString&)),this,TQT_SLOT(slotDirItemCreated(const TQString&)));
        connect(m_pList->m_DirWatch,TQT_SIGNAL(deleted(const TQString&)),this,TQT_SLOT(slotDirItemDeleted(const TQString&)));
        /* seems that recursive does not work */
        if (m_pList->m_DirWatch) {
            m_pList->m_DirWatch->addDir(baseUri()+"/",false,false);
            m_pList->m_DirWatch->startScan(true);
        }
    }
    bool result = checkDirs(baseUri(),0);
    if (result && isWorkingCopy()) {
        chdir(baseUri().local8Bit());
        if (firstChild()) firstChild()->setOpen(true);
    }
    if (!result) {
        setBaseUri("");
        setNetworked(false);
        clear();
    }
    m_pList->m_fileTip->setOptions(!isNetworked()&&Kdesvnsettings::display_file_tips()&&
        TQToolTip::isGloballyEnabled(),true,6);

    if (result && isWorkingCopy()) {
        m_SvnWrapper->createModifiedCache(baseUri());
        if (Kdesvnsettings::start_updates_check_on_open()) {
             slotCheckUpdates();
        }
    }
    if (Kdesvnsettings::log_cache_on_open()) {
        kdDebug()<<"Starting logcache"<<endl;
        m_SvnWrapper->startFillCache(baseUri());
    }
    emit changeCaption(baseUri());
    emit sigUrlOpend(result);
    TQTimer::singleShot(1,this,TQT_SLOT(readSupportData()));
    enableActions();
    return result;
}

void tdesvnfilelist::closeMe()
{
    m_SvnWrapper->killallThreads();

    selectAll(false);
    clear();
    setWorkingCopy("");
    setNetworked(false);
    setWorkingCopy(false);
    setBaseUri("");

    emit changeCaption("");
    emit sigUrlOpend(false);

    enableActions();
    m_SvnWrapper->reInitClient();
    delete m_pList->m_DirWatch;
    m_pList->m_DirWatch = 0;
    m_pList->m_fileTip->setItem(0);
}

bool tdesvnfilelist::checkDirs(const TQString&_what,FileListViewItem * _parent)
{
    TQString what = _what;
    svn::StatusEntries dlist;
    while (what.endsWith("/")) {
        what.truncate(what.length()-1);
    }
    // prevent this from checking unversioned folder. FIXME: what happen when we do open url on a non-working-copy folder??
    if (!isWorkingCopy()|| (!_parent) || ((_parent) && (_parent->isVersioned()))) {
        if (!m_SvnWrapper->makeStatus(what,dlist,m_pList->m_remoteRevision) ) {
            kdDebug() << "unable makeStatus" <<endl;
            return false;
        }
    } else {
        checkUnversionedDirs(_parent);
        return true;
    }
    svn::StatusEntries neweritems;
    m_SvnWrapper->getaddedItems(what,neweritems);
    dlist+=neweritems;
    bool ownupdates = true;
    //kdDebug() << "makeStatus on " << what << " created: " << dlist.count() << "items" <<endl;

    if (isUpdatesEnabled()) {
        viewport()->setUpdatesEnabled(false);
    } else {
        ownupdates=false;
    }
    svn::StatusEntries::iterator it = dlist.begin();
    FileListViewItem * pitem = 0;
    bool main_found = false;
    for (;it!=dlist.end();++it) {
        //kdDebug() << "iterate over it: " << (*it)->entry().url() << endl;

        // current item is not versioned
        if (!(*it)->isVersioned() && !filterOut((*it))) {
            // if empty, we may want to create a default svn::Status for each folder inside this _parent
            // iterate over TQDir and create new filelistviewitem
            checkUnversionedDirs(_parent);
        }

        if ((*it)->path()==what||TQString::compare((*it)->entry().url(),what)==0){
            if (!_parent) {
                pitem = new FileListViewItem(this,*it);
                //kdDebug()<< "CheckDirs::creating new FileListViewitem as parent " + (*it)->path() << endl;
                m_Dirsread[pitem->fullName()]=true;
                pitem->setDropEnabled(true);
            }
            dlist.erase(it);
            main_found = true;
            break;
        }
    }
    if (_parent) {
        pitem = _parent;
    }
    insertDirs(pitem,dlist);
    if (ownupdates) {
        kdDebug()<<"Enable update"<<endl;
        viewport()->setUpdatesEnabled(true);
        viewport()->repaint();
    }
    return true;
}

void tdesvnfilelist::insertDirs(FileListViewItem * _parent,svn::StatusEntries&dlist)
{
    svn::StatusEntries::iterator it;
#if 0
    KFileItemList oneItem;
#endif

    TQTime _t;
    _t.start();
    for (it = dlist.begin();it!=dlist.end();++it) {
/*        if (_t.elapsed()>300) {
           viewport()->setUpdatesEnabled(true);
            viewport()->repaint();
            viewport()->setUpdatesEnabled(false);
            _t.restart();
        }*/
        if (filterOut((*it)))
        {
            continue;
        }
        FileListViewItem * item;
        if (!_parent) {
            item = new FileListViewItem(this,*it);
        } else {
            if ( (item = _parent->findChild( (*it)->path() ))  ) {
                delete item;
            }
            item = new FileListViewItem(this,_parent,*it);
        }
        if (item->isDir()) {
            m_Dirsread[item->fullName()]=false;
            item->setDropEnabled(true);
            if (isWorkingCopy()) {
                m_pList->m_DirWatch->addDir(item->fullName());
            }
        } else if (isWorkingCopy()) {
            m_pList->m_DirWatch->addFile(item->fullName());
        }
    }
}

/* newdir is the NEW directory! just required if local */
void tdesvnfilelist::slotDirAdded(const TQString&newdir,FileListViewItem*k)
{
    if (k) {
        k->refreshStatus();
    }
    if (!isWorkingCopy()) {
        if (k) {
            k->removeChilds();
            m_Dirsread[k->fullName()]=false;
            if (checkDirs(k->fullName(),k)) {
                m_Dirsread[k->fullName()]=true;
            } else {
                kdDebug()<<"Checkdirs failed"<<endl;
            }
            return;
        }
        TQListViewItem*temp;
        while ((temp=firstChild())) {
            delete temp;
        }
        m_Dirsread.clear();
        checkDirs(baseUri(),0);
        return;
    }
    svn::StatusPtr stat;
    try {
        stat = m_SvnWrapper->svnclient()->singleStatus(newdir);
    } catch (const svn::ClientException&e) {
        m_LastException = e.msg();
        kdDebug()<<"Catched on singlestatus"<< endl;
        emit sigLogMessage(m_LastException);
        return;
    }
    FileListViewItem * item,*pitem;
    pitem = k;
    if (!pitem) {
        pitem = (FileListViewItem*)firstChild();
        if (pitem->fullName()!=baseUri()) {
            pitem = 0;
        }
    }
    if (!pitem) {
        item = new FileListViewItem(this,stat);
    } else {
        item = new FileListViewItem(this,pitem,stat);
    }
    if (item->isDir()) {
        m_Dirsread[item->fullName()]=false;
        item->setDropEnabled(true);
        if (isWorkingCopy()) {
            m_pList->m_DirWatch->addDir(item->fullName());
        }
    } else if (isWorkingCopy()) {
        m_pList->m_DirWatch->addFile(item->fullName());
    }
}

tdesvnfilelist::~tdesvnfilelist()
{
    delete m_pList;
    delete m_SelectedItems;
    SshAgent ssh;
    ssh.killSshAgent();
}

void tdesvnfilelist::slotItemRead(TQListViewItem*aItem)
{
    if (!aItem) return;
    CursorStack a(TQt::BusyCursor);
    FileListViewItem* k = static_cast<FileListViewItem*>( aItem );
    bool _ex = true;
    if (isWorkingCopy()) {
        TQDir d(k->fullName()); //FIXME: remove this as soon as we've been able to set entry->kind in Checkdirs
        _ex = k->isDir()||d.exists();
    } else {
        _ex = k->isDir();
    }

    if (_ex &&(m_Dirsread.find(k->fullName())==m_Dirsread.end()||m_Dirsread[k->fullName()]==false)) {
        if (checkDirs(k->fullName(),k)) {
            m_Dirsread[k->fullName()]=true;
        } else {
            emit sigListError();
        }
    }
}

void tdesvnfilelist::slotReinitItem(SvnItem*item)
{
    if (!item) {
        kdDebug()<<"tdesvnfilelist::slotReinitItem(SvnItem*item): item == null" << endl;
        return;
    }
    FileListViewItem*k = item->fItem();
    if (!k) {
        kdDebug()<<"tdesvnfilelist::slotReinitItem(SvnItem*item): k == null" << endl;
    }
    refreshItem(k);
    if (!k) {
        return;
    }
    if (k->isDir()) {
        k->removeChilds();
        m_Dirsread[k->fullName()]=false;;
    }
}

void tdesvnfilelist::enableActions()
{
    bool isopen = baseUri().length()>0;
    int c = allSelected()->count();
    bool single = c==1&&isopen;
    bool multi = c>1&&isopen;
    bool none = c==0&&isopen;
    bool dir = false;
    bool unique = uniqueTypeSelected();
    bool remote_enabled=isopen&&m_SvnWrapper->doNetworking();

    if (single && allSelected()->at(0)->isDir()) {
        dir = true;
    }

    bool conflicted = single && allSelected()->at(0)->isConflicted();
    TDEAction * temp = 0;
    /* local and remote actions */
    /* 1. actions on dirs AND files */
    temp = filesActions()->action("make_svn_log");
    if (temp) {
        temp->setEnabled(single||none);
    }
    temp = filesActions()->action("make_last_change");
    if (temp) {
        temp->setEnabled(isopen);
    }

    temp = filesActions()->action("make_svn_log_full");
    if (temp) {
        temp->setEnabled(single||none);
    }
    temp = filesActions()->action("make_svn_tree");
    if (temp) {
        temp->setEnabled(single||none);
    }
    temp = filesActions()->action("make_svn_partialtree");
    if (temp) {
        temp->setEnabled(single||none);
    }

    temp = filesActions()->action("make_svn_property");
    if (temp) {
        temp->setEnabled(single);
    }
    temp = filesActions()->action("get_svn_property");
    if (temp) {
        temp->setEnabled(single);
    }
    m_DelCurrent->setEnabled( (multi||single));
    m_LockAction->setEnabled( (multi||single));
    m_UnlockAction->setEnabled( (multi||single));
    m_IgnoreAction->setEnabled((single)&&singleSelected()->parent()!=0&&!singleSelected()->isRealVersioned());

    m_RenameAction->setEnabled(single && (!isWorkingCopy()||singleSelected()!=firstChild()));
    m_CopyAction->setEnabled(single && (!isWorkingCopy()||singleSelected()!=firstChild()));

    /* 2. only on files */
    m_BlameAction->setEnabled(single&&!dir&&remote_enabled);
    m_BlameRangeAction->setEnabled(single&&!dir&&remote_enabled);
    m_CatAction->setEnabled(single&&!dir);
    /* 3. actions only on dirs */
    m_MkdirAction->setEnabled(dir||none && isopen);
    m_switchRepository->setEnabled(isWorkingCopy()&& (single||none));
    m_changeToRepository->setEnabled(isWorkingCopy());
    m_ImportDirsIntoCurrent->setEnabled(dir);
    temp = filesActions()->action("make_svn_relocate");
    if (temp) {
        temp->setEnabled(isWorkingCopy()&& (single||none));
    }
    m_ExportCurrentAction->setEnabled(((single&&dir)||none));

    /* local only actions */
    /* 1. actions on files AND dirs*/
    m_AddCurrent->setEnabled( (multi||single) && isWorkingCopy());
    m_RevertAction->setEnabled( (multi||single) && isWorkingCopy());
    m_ResolvedAction->setEnabled( (multi||single) && isWorkingCopy());
    temp = filesActions()->action("make_try_resolve");
    if (temp) {
        temp->setEnabled(conflicted && !dir);
    }

    m_InfoAction->setEnabled(isopen);
    m_MergeRevisionAction->setEnabled(single&&isWorkingCopy());
    temp = filesActions()->action("make_svn_merge");
    if (temp) {
        temp->setEnabled(single||none);
    }
    temp = filesActions()->action("make_svn_addrec");
    if (temp) {
        temp->setEnabled( (multi||single) && isWorkingCopy());
    }
    m_UpdateHead->setEnabled(isWorkingCopy()&&isopen&&remote_enabled);
    m_UpdateRev->setEnabled(isWorkingCopy()&&isopen&&remote_enabled);
    m_commitAction->setEnabled(isWorkingCopy()&&isopen&&remote_enabled);

    temp = filesActions()->action("make_svn_basediff");
    if (temp) {
        temp->setEnabled(isWorkingCopy()&&(single||none));
    }
    temp = filesActions()->action("make_svn_headdiff");
    if (temp) {
        temp->setEnabled(isWorkingCopy()&&(single||none)&&remote_enabled);
    }

    /// @todo check if all items have same type
    temp = filesActions()->action("make_svn_itemsdiff");
    if (temp) {
        temp->setEnabled(multi && c==2 && unique && remote_enabled);
    }

    /* 2. on dirs only */
    m_CleanupAction->setEnabled(isWorkingCopy()&& (dir||none));
    temp = filesActions()->action("make_check_unversioned");
    if (temp) {
        temp->setEnabled(isWorkingCopy()&& ((dir&&single) || none));
    }

    /* remote actions only */
    m_CheckoutCurrentAction->setEnabled( ((single&&dir)||none) && !isWorkingCopy() && remote_enabled);
    /* independ actions */
    m_CheckoutAction->setEnabled(remote_enabled);
    m_ExportAction->setEnabled(true);
    m_RefreshViewAction->setEnabled(isopen);

    temp = filesActions()->action("make_revisions_diff");
    if (temp) {
        temp->setEnabled(isopen);
    }
    temp = filesActions()->action("make_revisions_cat");
    if (temp) {
        temp->setEnabled(isopen && !dir && single);
    }
    temp = filesActions()->action("switch_browse_revision");
    if (temp) {
        temp->setEnabled(!isWorkingCopy()&&isopen);
    }
    temp = filesActions()->action("make_check_updates");
    if (temp) {
        temp->setEnabled(isWorkingCopy()&&isopen && remote_enabled);
    }
    temp = filesActions()->action("openwith");
    if (temp) {
        temp->setEnabled(kapp->authorizeTDEAction("openwith")&&single&&!dir);
    }

    temp = filesActions()->action("update_log_cache");
    if (temp) {
        temp->setEnabled(remote_enabled);
        if (!m_SvnWrapper->threadRunning(SvnActions::fillcachethread)) {
            temp->setText(i18n("Update log cache"));
        } else {
            temp->setText(i18n("Stop updating the logcache"));
        }
    }
}

void tdesvnfilelist::slotSelectionChanged()
{
    m_pList->stopProptimer();
    if (m_SelectedItems==0) {
        m_SelectedItems = new FileListViewItemList;
        m_SelectedItems->setAutoDelete(false);
    }
    m_SelectedItems->clear();

    TQListViewItemIterator it( this, TQListViewItemIterator::Selected );
    while ( it.current() ) {
        m_SelectedItems->append( static_cast<FileListViewItem*>(it.current()) );
        ++it;
    }
    enableActions();
    m_pList->startProptimer();
}

/*!
    \fn tdesvnfilelist::slotClientException(const TQString&)
 */
void tdesvnfilelist::slotClientException(const TQString&what)
{
    emit sigLogMessage(what);
    KMessageBox::sorry(TQT_TQWIDGET(TDEApplication::activeModalWidget()),what,i18n("SVN Error"));
}


/*!
    \fn tdesvnfilelist::slotNotifyMessage(const TQString&)
 */
void tdesvnfilelist::slotNotifyMessage(const TQString&what)
{
    emit sigLogMessage(what);
    kapp->processEvents(20);
}

void tdesvnfilelist::slotChangeToRepository()
{
    if (!isWorkingCopy()) {
        return;
    }
    FileListViewItem*k = static_cast<FileListViewItem*>(firstChild());
    /* huh... */
    if (!k) return;
    svn::InfoEntry i;
    if (!m_SvnWrapper->singleInfo(k->Url(),svn::Revision::UNDEFINED,i)) {
        return;
    }
    if (i.reposRoot().isEmpty()) {
        KMessageBox::sorry(TQT_TQWIDGET(TDEApplication::activeModalWidget()),i18n("Could not retrieve repository of working copy."),i18n("SVN Error"));
    } else {
        sigSwitchUrl(i.reposRoot());
    }
}

void tdesvnfilelist::slotItemDoubleClicked(TQListViewItem*item)
{
    if (!item) return;

    FileListViewItem*fki = static_cast<FileListViewItem*>(item);
    if (fki->isDir()) {
        if (fki->isOpen()) {
            fki->setOpen(false);
        } else {
            fki->setOpen(true);
        }
        return;
    }
    svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision);
    TQString feditor = Kdesvnsettings::external_display();
    if ( feditor.compare("default") == 0 ) {
        KURL::List lst;
        lst.append(fki->kdeName(rev));
        TDETrader::OfferList li = offersList(fki,true);
        if (li.count()==0||li.first()->exec().isEmpty()) {
            li = offersList(fki);
        }
        if (li.count()>0&&!li.first()->exec().isEmpty()) {
            KService::Ptr ptr = li.first();
            KRun::run( *ptr, lst);
        } else {
            KRun::displayOpenWithDialog(lst);
        }
    } else {
        if ( KRun::runCommand(feditor + " " +  fki->kdeName(rev).prettyURL()) <= 0) {
            KMessageBox::error(this,i18n("Failed: %1 %2").arg(feditor).arg(fki->fullName()));
        }
    }
}

void tdesvnfilelist::slotCleanupAction()
{
    if (!isWorkingCopy()) return;
    FileListViewItem*which= singleSelected();
    if (!which) which = static_cast<FileListViewItem*>(firstChild());
    if (!which||!which->isDir()) return;
    if (m_SvnWrapper->makeCleanup(which->fullName())) {
        which->refreshStatus(true);
    }
}

void tdesvnfilelist::slotResolved()
{
    if (!isWorkingCopy()) return;
    FileListViewItem*which= singleSelected();
    if (!which) which = static_cast<FileListViewItem*>(firstChild());
    if (!which) return;
    m_SvnWrapper->slotResolved(which->fullName());
    which->refreshStatus(true);
    slotRescanIcons(false);
}

void tdesvnfilelist::slotTryResolve()
{
    if (!isWorkingCopy()) return;
    FileListViewItem*which= singleSelected();
    if (!which || which->isDir()) {
        return;
    }
    m_SvnWrapper->slotResolve(which->fullName());
}

template<class T> KDialogBase* tdesvnfilelist::createDialog(T**ptr,const TQString&_head,bool OkCancel,const char*name,bool showHelp)
{
    int buttons = KDialogBase::Ok;
    if (OkCancel) {
        buttons = buttons|KDialogBase::Cancel;
    }
    if (showHelp) {
        buttons = buttons|KDialogBase::Help;
    }
    KDialogBase * dlg = new KDialogBase(
        TQT_TQWIDGET(TQT_TQWIDGET(TDEApplication::activeModalWidget())),
        name,
        true,
        _head,
        buttons);

    if (!dlg) return dlg;
    TQWidget* Dialog1Layout = dlg->makeVBoxMainWidget();
    *ptr = new T(Dialog1Layout);
    dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),name?name:"standard_size"));
    return dlg;
}

void tdesvnfilelist::slotImportDirsIntoCurrent()
{
    slotImportIntoCurrent(true);
}

/*!
    \fn tdesvnfilelist::slotImportIntoCurrent()
 */
void tdesvnfilelist::slotImportIntoCurrent(bool dirs)
{
    if (allSelected()->count()>1) {
        KMessageBox::error(this,i18n("Cannot import into multiple targets!"));
        return;
    }
    TQString targetUri;
    if (allSelected()->count()==0) {
        targetUri=baseUri();
    } else {
        targetUri = allSelected()->at(0)->Url();
    }
    KURL uri;
    if (dirs) uri = KFileDialog::getExistingDirectory(TQString(),this,"Import files from folder");
    else uri = KFileDialog::getImageOpenURL(TQString(),this,"Import file");

    if (uri.url().isEmpty()) return;

    if ( !uri.protocol().isEmpty() && uri.protocol()!="file") {
        KMessageBox::error(this,i18n("Cannot import into remote targets!"));
        return;
    }
    slotImportIntoDir(uri,targetUri,dirs);
}

void tdesvnfilelist::slotImportIntoDir(const KURL&importUrl,const TQString&target,bool dirs)
{
    Logmsg_impl*ptr;
    Importdir_logmsg*ptr2 = 0;

    KDialogBase*dlg;
    KURL uri = importUrl;
    TQString targetUri = target;
    while (targetUri.endsWith("/")) {
        targetUri.truncate(targetUri.length()-1);
    }

    if (dirs) {
         dlg = createDialog(&ptr2,TQString(i18n("Import log")),true,"import_log_msg");
         ptr = ptr2;
         ptr2->createDirboxDir("\""+uri.fileName(true)+"\"");
    } else {
        dlg = createDialog(&ptr,TQString(i18n("Import log")),true,"import_log_msg");
    }

    if (!dlg) return;

    ptr->initHistory();
    if (dlg->exec()!=TQDialog::Accepted) {
        ptr->saveHistory(true);
        dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"import_log_msg",false);
        delete dlg;
        return;
    }
    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"import_log_msg",false);

    TQString logMessage = ptr->getMessage();
    svn::Depth rec = ptr->getDepth();
    ptr->saveHistory(false);
    uri.setProtocol("");
    TQString iurl = uri.path();
    while (iurl.endsWith("/")) {
        iurl.truncate(iurl.length()-1);
    }

    if (dirs && ptr2 && ptr2->createDir()) {
        targetUri+= "/"+uri.fileName(true);
    }
    if (ptr2) {
        m_SvnWrapper->slotImport(iurl,targetUri,logMessage,rec,ptr2->noIgnore(),ptr2->ignoreUnknownNodes());
    } else {
        m_SvnWrapper->slotImport(iurl,targetUri,logMessage,rec,false,false);
    }

    if (!isWorkingCopy()) {
        if (allSelected()->count()==0) {
            refreshCurrentTree();
        } else {
            refreshCurrent(allSelected()->at(0));
        }
    }
    delete dlg;
}

void tdesvnfilelist::readSupportData()
{
    /// this moment empty cause no usagedata explicit used by tdesvnfilelist
}

void tdesvnfilelist::refreshCurrentTree()
{
    TQTime t;
    t.start();
    FileListViewItem*item = static_cast<FileListViewItem*>(firstChild());
    if (!item) return;
    //m_pList->stopScan();
    m_pList->m_fileTip->setItem(0);
    kapp->processEvents();
    setUpdatesEnabled(false);
    if (item->fullName()==baseUri()) {
        if (!refreshItem(item)) {
            setUpdatesEnabled(true);
            viewport()->repaint();
            return;
        } else {
            refreshRecursive(item);
        }
    } else {
        refreshRecursive(0);
    }
    if (isWorkingCopy()) {
        m_SvnWrapper->createModifiedCache(baseUri());
    }
    kdDebug()<<"Refresh time: "<<t.elapsed()<<" ms"<<endl;
    setUpdatesEnabled(true);
    viewport()->repaint();
    TQTimer::singleShot(1,this,TQT_SLOT(readSupportData()));
    //m_pList->startScan();
}

void tdesvnfilelist::refreshCurrent(SvnItem*cur)
{
    if (!cur||!cur->fItem()) {
        refreshCurrentTree();
        return;
    }
    kapp->processEvents();
    setUpdatesEnabled(false);
    refreshRecursive(cur->fItem());
    setUpdatesEnabled(true);
    viewport()->repaint();
}

bool tdesvnfilelist::refreshRecursive(FileListViewItem*_parent,bool down)
{
    FileListViewItem*item;
    if (_parent) {
        item = static_cast<FileListViewItem*>(_parent->firstChild());
    } else {
        item = static_cast<FileListViewItem*>(firstChild());
    }

    if (!item) return false;
    kapp->processEvents();

    FileListViewItemList currentSync;
    currentSync.setAutoDelete(false);

    while (item) {
        currentSync.append(item);
        item = static_cast<FileListViewItem*>(item->nextSibling());
    }

    TQString what = (_parent!=0?_parent->fullName():baseUri());
    svn::StatusEntries dlist;

    if (!m_SvnWrapper->makeStatus(what,dlist,m_pList->m_remoteRevision)) {
        kdDebug()<<"Fehler bei makestatus fuer "<<what <<endl;
        return false;
    }
    if (isWorkingCopy()) {
        svn::StatusEntries neweritems;
        m_SvnWrapper->getaddedItems(what,neweritems);
        dlist+=neweritems;
    }

    svn::StatusEntries::iterator it = dlist.begin();
    FileListViewItem*k;
    bool gotit = false;
    bool dispchanged = false;
    for (;it!=dlist.end();++it) {
        gotit = false;
        if ((*it)->path()==what) {
            continue;
        }
        FileListViewItemListIterator clistIter(currentSync);
        while ( (k=clistIter.current()) ) {
            ++clistIter;
            if (k->fullName()==(*it)->path()) {
                currentSync.removeRef(k);
                k->updateStatus(*it);
                if (filterOut(k)) {
                    dispchanged=true;
                    delete k;
                }
                gotit = true;
                break;
            }
        }
        if (!gotit &&!filterOut((*it)) ) {
            dispchanged = true;
            FileListViewItem * item;
            if (!_parent) {
                item = new FileListViewItem(this,*it);
            } else {
                item = new FileListViewItem(this,_parent,*it);
            }
            if (item->isDir()) {
                m_Dirsread[item->fullName()]=false;
                item->setDropEnabled(true);
            }
            if (isWorkingCopy()) {
                if (item->isDir()) {
                    m_pList->m_DirWatch->addDir(item->fullName());
                } else {
                    m_pList->m_DirWatch->addFile(item->fullName());
                }
            }
        }
    }
    FileListViewItemListIterator dIter(currentSync);
#ifndef NDEBUG
    slotSelectionChanged();
    kdDebug() << "Selected items " << m_SelectedItems->count()<< endl;
#endif
    while ( (k=dIter.current()) ) {
        ++dIter;
        delete k;
        // @todo just for debugging!
#ifndef NDEBUG
        m_SelectedItems->clear();
        TQListViewItemIterator qlvit( this, TQListViewItemIterator::Selected );
        while ( qlvit.current() ) {
            m_SelectedItems->append( static_cast<FileListViewItem*>(qlvit.current()) );
            ++qlvit;
        }
        kdDebug() << "Selected items " << m_SelectedItems->count() << endl;
#endif
    }
    if (_parent) {
        item = static_cast<FileListViewItem*>(_parent->firstChild());
    } else {
        item = static_cast<FileListViewItem*>(firstChild());
    }
    if (!down) {
        return dispchanged;
    }
    while (item) {
        if (item->isDir()) {
            if ((m_Dirsread.find(item->fullName())!=m_Dirsread.end()&&m_Dirsread[item->fullName()]==true)) {
                if (item->childCount()==0) {
                    checkDirs(item->fullName(),item);
                    dispchanged = true;
                } else {
                    dispchanged = refreshRecursive(item)?true:dispchanged;
                }
            }
        }
        item = static_cast<FileListViewItem*>(item->nextSibling());
    }
    return dispchanged;
}

TDETrader::OfferList tdesvnfilelist::offersList(SvnItem*item,bool execOnly)
{
    TDETrader::OfferList offers;
    if (!item) {
        return offers;
    }
    TQString constraint;
    if (execOnly) {
        constraint = "Type == 'Application' or (exist Exec)";
    } else {
        constraint = "Type == 'Application'";
    }
    offers = TDETrader::self()->query(item->mimeType()->name(), constraint);

    return offers;
}

void tdesvnfilelist::slotContextMenuRequested(TQListViewItem */* _item */, const TQPoint &, int)
{
//    FileListViewItem*item = static_cast<FileListViewItem*>(_item);
    bool isopen = baseUri().length()>0;
    SvnItemList l;
    SelectionList(&l);

    TQString menuname;

    if (!isopen) {
        menuname="empty";
    } else if (isWorkingCopy()) {
        menuname="local";
    } else {
        menuname="remote";
    }
    if (l.count()==0) {
        menuname+="_general";
    } else if (l.count()>1){
        menuname+="_context_multi";
    } else {
        menuname+="_context_single";
        if (isWorkingCopy()) {
            if (l.at(0)->isRealVersioned()) {
                if (l.at(0)->isConflicted()) {
                    menuname+="_conflicted";
                } else {
                    menuname+="_versioned";
                    if (l.at(0)->isDir()) {
                        menuname+="_dir";
                    }
                }
            } else {
                menuname+="_unversioned";
            }
        } else if (l.at(0)->isDir()) {
            menuname+="_dir";
        }
    }

    TQWidget * target;
    emit sigShowPopup(menuname,&target);
    TQPopupMenu *popup = static_cast<TQPopupMenu *>(target);
    if (!popup) {
        kdDebug()<<"Error getting popupMenu"<<endl;
        return;
    }

    TDETrader::OfferList offers;
    OpenContextmenu*me=0;
    TDEAction*temp = 0;

    int id = -1;

    if (l.count()==1) offers = offersList(l.at(0));

    if (l.count()==1&&!l.at(0)->isDir()) {
        temp = filesActions()->action("openwith");
        if (offers.count()>0) {
            svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision);
            me= new OpenContextmenu(l.at(0)->kdeName(rev),offers,0,0);
            id = popup->insertItem(i18n("Open With..."),me);
        } else {
            temp = filesActions()->action("openwith");
            if (temp) {
                temp->plug(popup);
            }
        }
    }
    popup->exec(TQCursor::pos());
    if (id>-1) {
        popup->removeItem(id);
    }
    delete me;
    if (temp) {
        temp->unplug(popup);
    }
}

/**
* Overridden virtuals for TQt drag 'n drop (XDND)
*/
void tdesvnfilelist::contentsDragEnterEvent(TQDragEnterEvent *event)
{
    TQListViewItem*item;
    bool ok = validDropEvent(event,item);
    if (ok) {
        event->accept();
    } else {
        event->ignore();
    }
}

//void tdesvnfilelist::startDrag()
TQDragObject* tdesvnfilelist::dragObject()
{
    m_pList->m_fileTip->setItem(0);
    TQListViewItem * m_pressedItem = currentItem();
    if (!m_pressedItem) {
        return 0;
    }
    TQPixmap pixmap2;
    KURL::List urls = selectedUrls();
    if (urls.count()==0) {
        return 0;
    }
    if (!viewport()->hasFocus()) {
        kdDebug()<<"Set focus"<<endl;
        viewport()->setFocus();
    }
    kdDebug() << "dragObject: " << urls << endl;
    bool pixmap0Invalid = !m_pressedItem->pixmap(0) || m_pressedItem->pixmap(0)->isNull();
    if (( urls.count() > 1 ) || (pixmap0Invalid)) {
      int iconSize = Kdesvnsettings::listview_icon_size();;
      iconSize = iconSize ? iconSize : tdesvnPartFactory::instance()->iconLoader()->currentSize( TDEIcon::Small ); // Default = small
      pixmap2 = DesktopIcon( "application-vnd.tde.tdemultiple", iconSize );
      if ( pixmap2.isNull() ) {
          kdWarning() << "Could not find multiple pixmap" << endl;
      }
    }

    KURLDrag *drag;
    drag = new KURLDrag(urls,viewport());

    /* workaround for KURL::Drag - it always forget the revision part on drop :( */
    if (!isWorkingCopy()) {
        TQStrList l;
        TQString t;
        KURL::List::ConstIterator it = urls.begin();
        for (;it!=urls.end();++it) {
            l.append((*it).prettyURL().ascii());
        }
        drag->setUris(l);
    }

    drag->setExportAsText(true);
    if ( !pixmap2.isNull() )
        drag->setPixmap( pixmap2 );
    else if ( !pixmap0Invalid )
        drag->setPixmap( *m_pressedItem->pixmap( 0 ) );

    return drag;
}

void tdesvnfilelist::contentsDragLeaveEvent( TQDragLeaveEvent * )
{
    cleanHighLighter();
}

bool tdesvnfilelist::acceptDrag(TQDropEvent *event)const
{
    return KURLDrag::canDecode(event);
}

bool tdesvnfilelist::validDropEvent(TQDropEvent*event,TQListViewItem*&item)
{
    if (!event) return false;
    if (!isWorkingCopy()) {
        if (m_pList->m_remoteRevision!=svn::Revision::HEAD) {
            item = 0;
            return false;
        }
    }
    bool ok = false;
    item = 0;
    if (KURLDrag::canDecode(event)) {
        KURL::List urlList;
        KURLDrag::decode( event, urlList );
        int count = urlList.count();
        if (count>0) {
            if (baseUri().length()==0) {
                ok = true;
            } else {
                TQPoint vp = contentsToViewport( event->pos() );
                item = isExecuteArea( vp ) ? itemAt( vp ) : 0L;
                FileListViewItem*which=static_cast<FileListViewItem*>(item);
                if (!isWorkingCopy()) {
                    if (event->source()!=viewport()){
                        ok = (!item || (which->isDir()))&&urlList[0].isLocalFile()&&count==1;
                    } else {
                        ok = (!item || (which->isDir() ));
                    }
                } else {
                    ok = (which && (which->isDir()));
                }
            }
        }
    }
    return ok;
}

void tdesvnfilelist::contentsDropEvent(TQDropEvent * event)
{
    TQListViewItem *item = 0;
    bool ok = validDropEvent(event,item);
    cleanHighLighter();
    if (ok) {
        dropped(event,item);
    } else {
        event->ignore();
    }
}

void tdesvnfilelist::contentsDragMoveEvent( TQDragMoveEvent* event)
{
    TQListViewItem * item;
    bool ok = validDropEvent(event,item);

    if (item && item!=m_pList->dragOverItem) {
        TQPoint vp = contentsToViewport( event->pos() );
        m_pList->dragOverItem=item;
        m_pList->dragOverPoint = vp;
        TQRect tmpRect = drawItemHighlighter(0, m_pList->dragOverItem);
        if (tmpRect!=m_pList->mOldDropHighlighter) {
            cleanHighLighter();
            m_pList->mOldDropHighlighter=tmpRect;
            viewport()->repaint(tmpRect);
            kapp->processEvents();
        }
    }
    if (ok) {
        event->accept();
    } else {
        event->ignore();
    }
}

void tdesvnfilelist::viewportPaintEvent(TQPaintEvent *ev)
{
    TDEListView::viewportPaintEvent(ev);
    if (m_pList->mOldDropHighlighter.isValid() && ev->rect().intersects(m_pList->mOldDropHighlighter)) {
        TQPainter painter(viewport());
        style().tqdrawPrimitive(TQStyle::PE_FocusRect, &painter, m_pList->mOldDropHighlighter, colorGroup(),
                TQStyle::Style_FocusAtBorder);
    }
}

void tdesvnfilelist::cleanHighLighter()
{
    if (m_pList->mOldDropHighlighter.isValid()) {
        TQRect rect=m_pList->mOldDropHighlighter;
        m_pList->mOldDropHighlighter=TQRect();
        viewport()->repaint(rect, true);
    }
}

/*!
    \fn tdesvnfilelist::slotMergeRevisions()
 */
void tdesvnfilelist::slotMergeRevisions()
{
    if (!isWorkingCopy()) return;
    FileListViewItem*which= singleSelected();
    if (!which) {
        return;
    }
    bool force,dry,rec,irelated,useExternal;
    Rangeinput_impl::revision_range range;
    if (!MergeDlg_impl::getMergeRange(range,&force,&rec,&irelated,&dry,&useExternal,this,"merge_range")) {
        return;
    }
    if (!useExternal) {
        m_SvnWrapper->slotMergeWcRevisions(which->fullName(),range.first,range.second,rec,!irelated,force,dry);
    } else {
        m_SvnWrapper->slotMergeExternal(which->fullName(),which->fullName(),which->fullName(),range.first,range.second,
                                         isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision,rec);
    }
    refreshItem(which);
    refreshRecursive(which);
}

void tdesvnfilelist::slotMerge()
{
    FileListViewItem*which= singleSelected();
    TQString src1,src2,target;
    if (isWorkingCopy()) {
        if (m_pList->merge_Target.isEmpty()) {
            target = which?which->fullName():baseUri();
        } else {
            target = m_pList->merge_Target;
        }
        src1 = m_pList->merge_Src1;
    } else {
        if (m_pList->merge_Src1.isEmpty()){
            src1 = which?which->fullName():baseUri();
        } else {
            src1 = m_pList->merge_Src1;
        }
        target = m_pList->merge_Target;
    }
    src2 = m_pList->merge_Src2;
    bool force,dry,rec,irelated,useExternal;
    Rangeinput_impl::revision_range range;
    MergeDlg_impl*ptr;
    KDialogBase*dlg = createDialog(&ptr,TQString(i18n("Merge")),true,"merge_dialog",true);
    if (!dlg) {
        return;
    }
    dlg->setHelp("merging-items","tdesvn");
    ptr->setDest(target);
    ptr->setSrc1(src1);
    ptr->setSrc2(src1);
    if (dlg->exec()==TQDialog::Accepted) {
        src1=ptr->Src1();
        src2=ptr->Src2();
        if (src2.isEmpty()) {
            src2 = src1;
        }
        target = ptr->Dest();
        m_pList->merge_Src2 = src2;
        m_pList->merge_Src1 = src1;
        m_pList->merge_Target = target;
        force = ptr->force();
        dry = ptr->dryrun();
        rec = ptr->recursive();
        irelated = ptr->ignorerelated();
        useExternal = ptr->useExtern();
        range = ptr->getRange();
        if (!useExternal) {
            m_SvnWrapper->slotMerge(src1,src2,target,range.first,range.second,
                                     isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision,
                                     rec,!irelated,force,dry);
        } else {
            m_SvnWrapper->slotMergeExternal(src1,src2,target,range.first,range.second,
                                             isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision,rec);
        }
        if (isWorkingCopy()) {
//            refreshItem(which);
//            refreshRecursive(which);
            refreshCurrentTree();
        }
    }

    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"merge_dialog",false);

    delete dlg;
}

void tdesvnfilelist::slotDropped(TQDropEvent* event,TQListViewItem*item)
{
    KURL::List urlList;
    TQMap<TQString,TQString> metaData;
    TQDropEvent::Action action = event->action();
    if (!event || m_pList->intern_dropRunning||!KURLDrag::decode( event, urlList, metaData)||urlList.count()<1) {
        return;
    }
    kdDebug()<<"slotDropped"<<endl;
    TQString tdir;
    if (item) {
        FileListViewItem*which = static_cast<FileListViewItem*>(item);
        clearSelection();
        which->setSelected(true);
        kapp->processEvents();
        tdir = which->fullName();
    } else {
        tdir = baseUri();
    }

    if (event->source()!=viewport()) {
        kdDebug()<<"Dropped from outside" << endl;
        if (baseUri().length()==0) {
            openURL(urlList[0]);
            event->acceptAction();
            return;
        }
        if (baseUri().length()>0 /*&& urlList[0].isLocalFile()*/) {
            TQString path = urlList[0].path();
            TQFileInfo fi(path);
            if  (!isWorkingCopy()) {
                slotImportIntoDir(urlList[0],tdir,fi.isDir());
            } else {
                //m_pList->stopScan();
                TDEIO::Job * job = 0L;
                job = TDEIO::copy(urlList,tdir);
                connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),TQT_SLOT( slotCopyFinished( TDEIO::Job * ) ) );
                dispDummy();
                event->acceptAction();
                return;
            }
        }
    } else {
        kdDebug()<<"Dropped from inside " << action << endl;
        int root_x, root_y, win_x, win_y;
        uint keybstate;
        TQDropEvent::Action action = TQDropEvent::UserAction;
        KeyState::keystate(&root_x,&root_y,&win_x,&win_y,&keybstate);
        if (keybstate&TQt::ControlButton) {
            kdDebug()<<"Control pressed" << endl;
            action = TQDropEvent::Copy;
        } else if (keybstate&TQt::ShiftButton) {
            kdDebug()<<"Shift pressed" << endl;
            action = TQDropEvent::Move;
        }
        /* converting urls to interal style */
        TQString nProto;
        if (isWorkingCopy()) {
            nProto="";
        } else {
            nProto = svn::Url::transformProtokoll(urlList[0].protocol());
        }
        KURL::List::Iterator it = urlList.begin();
        TQStringList l;
        for (;it!=urlList.end();++it) {
            l = TQStringList::split("?",(*it).prettyURL());
            if (l.size()>1) {
                (*it) = l[0];
            } else if (isWorkingCopy())
            {
                (*it) = KURL::fromPathOrURL( (*it).path());
            }
            (*it).setProtocol(nProto);
            kdDebug()<<"Dropped: "<<(*it)<<endl;
        }
        event->acceptAction();
        m_pList->intern_dropRunning=true;
        m_pList->intern_drops = urlList;
        m_pList->intern_drop_target=tdir;
        m_pList->intern_drop_action=action;
        m_pList->intern_drop_pos=TQCursor::pos();
        TQTimer::singleShot(0,this,TQT_SLOT(slotInternalDrop()));

//        internalDrop(action,urlList,tdir);
    }
}

void tdesvnfilelist::slotInternalDrop()
{
    TQDropEvent::Action action = m_pList->intern_drop_action;
    if (action==TQDropEvent::UserAction) {
         TQPopupMenu popup;
         popup.insertItem(SmallIconSet("goto"), i18n( "Move Here" ) + "\t" + KKey::modFlagLabel( KKey::SHIFT ), 2 );
         popup.insertItem(SmallIconSet("edit-copy"), i18n( "Copy Here" ) + "\t" + KKey::modFlagLabel( KKey::CTRL ), 1 );
         popup.insertSeparator();
         popup.insertItem(SmallIconSet("cancel"), i18n( "Cancel" ) + "\t" + KKey( TQt::Key_Escape ).toString(), 5);
         int result = popup.exec(m_pList->intern_drop_pos);
         switch (result) {
            case 1 : action = TQDropEvent::Copy; break;
            case 2 : action = TQDropEvent::Move; break;
            default:
            {
                m_pList->intern_dropRunning=false;
                return;
            }
         }
    }
    if (action==TQDropEvent::Move) {
        m_SvnWrapper->makeMove(m_pList->intern_drops,m_pList->intern_drop_target,false);
    } else {
        m_SvnWrapper->makeCopy(m_pList->intern_drops,m_pList->intern_drop_target,svn::Revision::HEAD);
    }
    m_pList->intern_dropRunning=false;
    refreshCurrentTree();
}

/*!
    \fn tdesvnfilelist::slotRename()
 */
void tdesvnfilelist::slotRename()
{
    copy_move(true);
}
void tdesvnfilelist::slotCopy()
{
    copy_move(false);
}

void tdesvnfilelist::copy_move(bool move)
{
    if (isWorkingCopy()&&singleSelected()==firstChild()) {
        return;
    }
    bool ok, force;
    FileListViewItem*which = singleSelected();
    if (!which) return;
    TQString nName =  CopyMoveView_impl::getMoveCopyTo(&ok,&force,move,
        which->fullName(),baseUri(),this,"move_name");
    if (!ok) {
        return;
    }
    if (move) {
        m_SvnWrapper->makeMove(which->fullName(),nName,force);
    } else {
        m_SvnWrapper->makeCopy(which->fullName(),nName, isWorkingCopy()?svn::Revision::HEAD:m_pList->m_remoteRevision);
    }
}

void tdesvnfilelist::slotCat()
{
    FileListViewItem*k = singleSelected();
    if (!k) return;
    m_SvnWrapper->slotMakeCat(isWorkingCopy()?svn::Revision::HEAD:m_pList->m_remoteRevision, k->fullName(),k->text(0),
        isWorkingCopy()?svn::Revision::HEAD:m_pList->m_remoteRevision,0);
}


/*!
    \fn tdesvnfilelist::slotCopyFinished( TDEIO::Job *)
 */
void tdesvnfilelist::slotCopyFinished( TDEIO::Job * job)
{
    if (m_pList->m_DirWatch) {
        m_pList->m_DirWatch->startScan(false);
    }
    if (job) {
        bool ok = true;
        tqApp->exit_loop();
        if (job->error()) {
            job->showErrorDialog(this);
            ok = false;
        }
        // always just connect a CopyJob here!!!!
        if (ok) {
            KURL::List lst = static_cast<TDEIO::CopyJob*>(job)->srcURLs();
            KURL turl = static_cast<TDEIO::CopyJob*>(job)->destURL();
            TQString base = turl.path(1);
            KURL::List::iterator iter;
            TQValueList<svn::Path> tmp;
            for (iter=lst.begin();iter!=lst.end();++iter) {
                tmp.push_back(svn::Path((base+(*iter).fileName(true))));
            }
            m_SvnWrapper->addItems(tmp,svn::DepthInfinity);
        }
        refreshCurrentTree();
    }
}



/*!
    \fn tdesvnfilelist::slotDelete()
 */
void tdesvnfilelist::slotDelete()
{
    m_deletePerfect = true;
    TQPtrList<FileListViewItem>*lst = allSelected();

    if (lst->count()==0) {
        KMessageBox::error(this,i18n("Nothing selected for delete"));
        return;
    }
    FileListViewItemListIterator liter(*lst);
    FileListViewItem*cur;
    //m_pList->stopScan();
    m_pList->m_fileTip->setItem(0);

    TQValueList<svn::Path> items;
    TQStringList displist;
    KURL::List tdeioList;
    while ((cur=liter.current())!=0){
        ++liter;
        if (!cur->isRealVersioned()) {
            KURL _uri; _uri.setPath(cur->fullName());
            tdeioList.append(_uri);
        } else {
            items.push_back(cur->fullName());
        }
        displist.append(cur->fullName());
    }
    int answer = KMessageBox::questionYesNoList(this,i18n("Really delete these entries?"),displist,i18n("Delete from repository"));
    if (answer!=KMessageBox::Yes) {
        return;
    }
    if (tdeioList.count()>0) {
        TDEIO::Job*aJob = TDEIO::del(tdeioList);
        connect(aJob,TQT_SIGNAL(result (TDEIO::Job *)),this,TQT_SLOT(slotDeleteFinished(TDEIO::Job*)));
        dispDummy();
    }
    if (m_deletePerfect && items.size()>0) {
        m_SvnWrapper->makeDelete(items);
    }
    refreshCurrentTree();
    //m_pList->startScan();
}

/*!
    \fn tdesvnfilelist::slotDeleteFinished(TDEIO::Job*)
 */
void tdesvnfilelist::slotDeleteFinished(TDEIO::Job*job)
{
    if (job) {
        tqApp->exit_loop();
        if (job->error()) {
            job->showErrorDialog(this);
            m_deletePerfect = false;
        }
    }
}

/*!
    \fn tdesvnfilelist::dispDummy()
 */
void tdesvnfilelist::dispDummy()
{
    // wait for job
    TQLabel dummy(this,0,WStyle_NoBorder|WShowModal);
    TQSize csize = size();
    dummy.setText(i18n("Please wait until job is finished"));
    dummy.resize(dummy.minimumSizeHint());
    if (dummy.width()<=width()&&dummy.height()<=height()) {
        dummy.move(csize.width()/2-dummy.width()/2,csize.height()/2-dummy.height()/2);
    }
    dummy.show();
    tqApp->enter_loop();
    dummy.hide();
}


/*!
    \fn tdesvnfilelist::slotLock()
 */
void tdesvnfilelist::slotLock()
{
    TQPtrList<FileListViewItem>*lst = allSelected();
    FileListViewItemListIterator liter(*lst);
    FileListViewItem*cur;
    if (lst->count()==0) {
        KMessageBox::error(this,i18n("Nothing selected for lock"));
        return;
    }
    KDialogBase*dlg;
    Logmsg_impl*ptr;
    dlg = createDialog(&ptr,TQString(i18n("Lock message")),true,"locking_log_msg");
    if (!dlg) return;
    ptr->initHistory();
    ptr->hideDepth(true);
    TQCheckBox*_stealLock = new TQCheckBox("",ptr,"create_dir_checkbox");
    _stealLock->setText(i18n("Steal lock?"));
    ptr->addItemWidget(_stealLock);
    ptr->m_keepLocksButton->hide();

    if (dlg->exec()!=TQDialog::Accepted) {
        ptr->saveHistory(true);
        delete dlg;
        return;
    }
    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"locking_log_msg",false);

    TQString logMessage = ptr->getMessage();
    bool steal = _stealLock->isChecked();
    ptr->saveHistory(false);

    TQStringList displist;
    while ((cur=liter.current())!=0){
        ++liter;
        displist.append(cur->fullName());
    }
    m_SvnWrapper->makeLock(displist,logMessage,steal);
    refreshCurrentTree();
}


/*!
    \fn tdesvnfilelist::slotUnlock()
 */
void tdesvnfilelist::slotUnlock()
{
    TQPtrList<FileListViewItem>*lst = allSelected();
    FileListViewItemListIterator liter(*lst);
    FileListViewItem*cur;
    if (lst->count()==0) {
        KMessageBox::error(this,i18n("Nothing selected for unlock"));
        return;
    }
    int res = KMessageBox::questionYesNoCancel(this,i18n("Break lock or ignore missing locks?"),i18n("Unlocking items"));
    if (res == KMessageBox::Cancel) {
        return;
    }
    bool breakit = res==KMessageBox::Yes;

    TQStringList displist;
    while ((cur=liter.current())!=0){
        ++liter;
        displist.append(cur->fullName());
    }
    m_SvnWrapper->makeUnlock(displist,breakit);
    refreshCurrentTree();
}


/*!
    \fn tdesvnfilelist::slotIgnore()
 */
void tdesvnfilelist::slotIgnore()
{
    SvnItem*item = singleSelected();
    if (!item || item->isRealVersioned()) return;
    if (m_SvnWrapper->makeIgnoreEntry(item,item->isIgnored())) {
        refreshCurrentTree();
    }
}


/*!
    \fn tdesvnfilelist::slotBlame()
 */
void tdesvnfilelist::slotBlame()
{
    SvnItem*k = singleSelected();
    if (!k) return;
    svn::Revision start(svn::Revision::START);
    svn::Revision end(svn::Revision::HEAD);
    m_SvnWrapper->makeBlame(start,end,k);
}


/*!
    \fn tdesvnfilelist::slotRangeBlame()
 */
void tdesvnfilelist::slotRangeBlame()
{
    SvnItem*k = singleSelected();
    if (!k) return;
    Rangeinput_impl*rdlg;
    KDialogBase*dlg = createDialog(&rdlg,TQString(i18n("Revisions")),true,"revisions_dlg");
    if (!dlg) {
        return;
    }
    if (dlg->exec()==TQDialog::Accepted) {
        Rangeinput_impl::revision_range r = rdlg->getRange();
        m_SvnWrapper->makeBlame(r.first,r.second,k);
    }
    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false);
    delete dlg;
}


void tdesvnfilelist::slotSimpleBaseDiff()
{
    FileListViewItem*kitem = singleSelected();
    if (isWorkingCopy())
    {
        chdir(baseUri().local8Bit());
    }

    TQString what;
    if (!kitem) {
        what==".";
    } else {
        what = relativePath(kitem);
    }
    // only possible on working copies - so we may say this values
    m_SvnWrapper->makeDiff(what,svn::Revision::BASE,svn::Revision::WORKING,svn::Revision::UNDEFINED,kitem?kitem->isDir():true);
}

void tdesvnfilelist::slotSimpleHeadDiff()
{
    FileListViewItem*kitem = singleSelected();
    TQString what;
    if (isWorkingCopy())
    {
        chdir(baseUri().local8Bit());
    }

    if (!kitem) {
        what=".";
    }else{
        what = relativePath(kitem);
    }
    // only possible on working copies - so we may say this values
    m_SvnWrapper->makeDiff(what,svn::Revision::WORKING,svn::Revision::HEAD,svn::Revision::UNDEFINED,kitem?kitem->isDir():true);
}

void tdesvnfilelist::slotDisplayLastDiff()
{
    FileListViewItem*kitem = singleSelected();
    TQString what;
    if (isWorkingCopy())
    {
        chdir(baseUri().local8Bit());
    }
    svn::Revision end = svn::Revision::PREV;
    if (!kitem) {
        if (isWorkingCopy()) {
            TQListViewItem*fi = firstChild();
            kitem = static_cast<FileListViewItem*>(fi);
            if (!kitem) {
                return;
            }
            what = relativePath(kitem);
        } else {
            what=baseUri();
        }
    }else{
        what = relativePath(kitem);
    }
    svn::Revision start;
    svn::InfoEntry inf;
    if (!kitem) {
        // it has to have an item when in working copy, so we know we are in repository view.
        if (!m_SvnWrapper->singleInfo(what,m_pList->m_remoteRevision,inf)) {
            return;
        }
        start = inf.cmtRev();
    } else {
        start = kitem->cmtRev();
    }
    if (!isWorkingCopy()) {
        if (!m_SvnWrapper->singleInfo(what,start.revnum()-1,inf)) {
            return;
        }
        end = inf.cmtRev();
    }
    m_SvnWrapper->makeDiff(what,end,what,start,realWidget());
}

void tdesvnfilelist::slotDiffPathes()
{
    TQPtrList<FileListViewItem>*lst = allSelected();

    if (lst->count()!=2 || !uniqueTypeSelected()) {
        return;
    }
    m_pList->m_fileTip->setItem(0);

    FileListViewItem*k1,*k2;
    k1 = lst->at(0);
    k2 = lst->at(1);
    TQString w1,w2;
    svn::Revision r1;

    if (isWorkingCopy()) {
        chdir(baseUri().local8Bit());
        w1 = relativePath(k1);
        w2 = relativePath(k2);
        r1 = svn::Revision::WORKING;
    } else {
        w1 = k1->fullName();
        w2 = k2->fullName();
        r1 = m_pList->m_remoteRevision;
    }
    m_SvnWrapper->makeDiff(w1,r1,w2,r1);
}

/*!
    \fn tdesvnfilelist::slotMkdir()
 */
void tdesvnfilelist::slotMkdir()
{
    SvnItem*k = singleSelected();
    TQString parentDir;
    if (k) {
        if (!k->isDir()) {
            KMessageBox::sorry(0,i18n("May not make subdirs of a file"));
            return;
        }
        parentDir=k->fullName();
    } else {
        parentDir=baseUri();
    }
    TQString ex = m_SvnWrapper->makeMkdir(parentDir);
    if (!ex.isEmpty()) {
        slotDirAdded(ex,static_cast<FileListViewItem*>(k));
    }
}

void tdesvnfilelist::slotMkBaseDirs()
{
    bool isopen = baseUri().length()>0;
    if (!isopen) {
        return;
    }
    TQString parentDir=baseUri();
    TQStringList targets;
    targets.append(parentDir+"/trunk");
    targets.append(parentDir+"/branches");
    targets.append(parentDir+"/tags");
    TQString msg = i18n("Automatic generated base layout by tdesvn");
    isopen = m_SvnWrapper->makeMkdir(targets,msg);
    if (isopen) {
        slotDirAdded(targets[0],0);
//        slotDirAdded(targets[1],0);
//        slotDirAdded(targets[2],0);
    }
}

/*!
    \fn tdesvnfilelist::slotDiffRevisions()
 */
void tdesvnfilelist::slotDiffRevisions()
{
    SvnItem*k = singleSelected();
    TQString what;
    if (isWorkingCopy())
    {
        chdir(baseUri().local8Bit());
    }

    if (!k) {
        what=(isWorkingCopy()?".":baseUri());
    }else{
        what = relativePath(k);
    }
    Rangeinput_impl*rdlg;
    KDialogBase*dlg = createDialog(&rdlg,TQString(i18n("Revisions")),true,"revisions_dlg");
    if (!dlg) {
        return;
    }
    if (dlg->exec()==TQDialog::Accepted) {
        Rangeinput_impl::revision_range r = rdlg->getRange();
        svn::Revision _peg=(isWorkingCopy()?svn::Revision::WORKING:remoteRevision());
        m_SvnWrapper->makeDiff(what,r.first,r.second,_peg,k?k->isDir():true);
    }
    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false);
    delete dlg;

}

void tdesvnfilelist::slotSelectBrowsingRevision()
{
    if (isWorkingCopy()) return;
    Rangeinput_impl*rdlg;
    KDialogBase*dlg = createDialog(&rdlg,TQString(i18n("Revisions")),true,"revisions_dlg");
    if (!dlg) {
        return;
    }
    rdlg->setStartOnly(true);
    if (dlg->exec()==TQDialog::Accepted) {
        Rangeinput_impl::revision_range r = rdlg->getRange();
        m_pList->m_remoteRevision= r.first;
        if (childCount()==0) {
            checkDirs(baseUri(),0);
        } else {
            refreshCurrentTree();
        }
    }
    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false);
    delete dlg;
}

/*!
    \fn tdesvnfilelist::slotRevisionCat()
 */
void tdesvnfilelist::slotRevisionCat()
{
    SvnItem*k = singleSelected();
    if (!k) return;
    Rangeinput_impl*rdlg;
    KDialogBase*dlg = createDialog(&rdlg,TQString(i18n("Revisions")),true,"revisions_dlg");
    if (!dlg) {
        return;
    }
    rdlg->setStartOnly(true);
    if (dlg->exec()==TQDialog::Accepted) {
        Rangeinput_impl::revision_range r = rdlg->getRange();
        m_SvnWrapper->slotMakeCat(r.first, k->fullName(),k->shortName(),r.first,0);
    }
    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false);
    delete dlg;
}


/*!
    \fn tdesvnfilelist::refreshItem(FileListViewItem*)
 */
bool tdesvnfilelist::refreshItem(FileListViewItem*item)
{
    if (!item) {
        return false;
    }
    try {
        item->setStat(svnclient()->singleStatus(item->fullName(),false,m_pList->m_remoteRevision));
    } catch (const svn::ClientException&e) {
        item->setStat(new svn::Status());
        return false;
    }
    return true;
}


/*!
    \fn tdesvnfilelist::slotCheckUpdates()
 */
void tdesvnfilelist::slotCheckUpdates()
{
    m_SvnWrapper->createUpdateCache(baseUri());
}

/*!
    \fn tdesvnfilelist::reinitItems(FileListViewItem*_item = 0)
 */
void tdesvnfilelist::reinitItems(FileListViewItem*_item)
{
    FileListViewItem*item;
    if (_item) {
        item = _item;
    } else {
        item = static_cast<FileListViewItem*>(firstChild());
    }
    if (!item) {
        return;
    }
    item->init();
    if (item->childCount()==0 && item->isOpen()) {
        m_Dirsread[item->fullName()]=false;;
        setEnabled(false);
        slotItemRead(item);
        setEnabled(true);
    } else {
        item = static_cast<FileListViewItem*>(item->firstChild());
        while(item) {
            reinitItems(item);
            item = static_cast<FileListViewItem*>(item->nextSibling());
        }
    }
}


/*!
    \fn tdesvnfilelist::slotInfo()
 */
void tdesvnfilelist::slotInfo()
{
    TQPtrList<SvnItem> lst;
    SelectionList(&lst);
    svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision);
    if (!isWorkingCopy()) {
        rev = m_pList->m_remoteRevision;
    }
    if (lst.count()==0) {
        if (!isWorkingCopy()) {
            m_SvnWrapper->makeInfo(baseUri(),rev,svn::Revision::UNDEFINED,Kdesvnsettings::info_recursive());
        } else {
            lst.append(SelectedOrMain());
        }
    }
    if (lst.count()>0) {
        m_SvnWrapper->makeInfo(lst,rev,rev,Kdesvnsettings::info_recursive());
    }
}


/*!
    \fn tdesvnfilelist::slotDirItemCreated(const TQString&)
 */
void tdesvnfilelist::slotDirItemCreated(const TQString&what)
{
    m_pList->stopDirTimer();
    m_pList->dirItems[what]='C';
    kdDebug()<<"slotDirItemCreated "<<what<<endl;
    m_pList->startDirTimer();
}


void tdesvnfilelist::updateParents(FileListViewItem*item)
{
    if (!item || !item->parent()) return;
    FileListViewItem*it = static_cast<FileListViewItem*>(item->parent());
    it->update();
    updateParents(it);
}

/*!
    \fn tdesvnfilelist::slotDirItemDirty(const TQString&)
 */
void tdesvnfilelist::slotDirItemDirty(const TQString&what)
{
    m_pList->stopDirTimer();
    m_pList->dirItems[what]='M';
    m_pList->startDirTimer();
}

void tdesvnfilelist::_propListTimeout()
{
    dispProperties(false);
}

void tdesvnfilelist::slotDisplayProperties()
{
    dispProperties(true);
}

void tdesvnfilelist::dispProperties(bool force)
{
    CursorStack a(TQt::BusyCursor);
    bool cache_Only = (!force && isNetworked() && !Kdesvnsettings::properties_on_remote_items());
    svn::PathPropertiesMapListPtr pm;
    SvnItem*k = singleSelected();
    if (!k || !k->isRealVersioned()) {
        emit sigProplist(svn::PathPropertiesMapListPtr(),false,TQString(""));
        return;
    }
    kdDebug()<<"Cacheonly: "<<cache_Only<<endl;
    svn::Revision rev(isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision);
    pm =m_SvnWrapper->propList(k->fullName(),rev,cache_Only);
    emit sigProplist(pm,isWorkingCopy(),k->fullName());
}

void tdesvnfilelist::_dirwatchTimeout()
{
    kdDebug()<<"dirtimer"<<endl;
    TQMap<TQString,TQChar>::Iterator it;
    m_pList->m_fileTip->setItem(0);
    viewport()->setUpdatesEnabled(false);
    bool repaintit=false;
    for (it=m_pList->dirItems.begin();it!=m_pList->dirItems.end();++it)
    {
        TQString what = it.key();
        TQChar c = it.data();
        FileListViewItem*item = findEntryItem(what);
        if (!item) {
            m_pList->m_DirWatch->removeDir(what);
            m_pList->m_DirWatch->removeFile(what);
            m_SvnWrapper->deleteFromModifiedCache(what);
            continue;
        }
        if (c == 'M') {
            if (!item->isNormal() && item->isRealVersioned()) {
                m_SvnWrapper->addModifiedCache(item->stat());
            } else {
                m_SvnWrapper->deleteFromModifiedCache(what);
            }
            if (item->isDir()) {
                if (item->isRealVersioned()) {
                    repaintit = refreshRecursive(item,false);
                } else {
                    TQListViewItem *_s;
                    while ( (_s=item->firstChild()))
                    {
                        delete _s;
                    }
                    checkUnversionedDirs(item);
                }
            }
            updateParents(static_cast<FileListViewItem*>(item->parent()));
        } else if (c=='D') {
            if (item->isDir()) {
                m_pList->m_DirWatch->removeDir(what);
            } else {
                m_pList->m_DirWatch->removeFile(what);
            }
            if (item->isDeleted()) {
                m_SvnWrapper->addModifiedCache(item->stat());
            } else if (!item->isMissing()) {
                TQFileInfo fi(what);
                if (!fi.exists()) {
                    FileListViewItem*p = static_cast<FileListViewItem*>(item->parent());
                    delete item;
                    repaintit=true;
                    item = 0;
                    if (p && p->isVersioned()) {
                        p->update();
                        updateParents(p);
                    }
                }
            }
        }
#if 0
        when add dirItemDirty is send for folder above so no need for checking add-flag.
        else {
            kdDebug()<<"Entry added: "<<what << endl;
        }
#endif
        if (item) {
            refreshItem(item);
        }
    }
    m_pList->dirItems.clear();
    viewport()->setUpdatesEnabled(true);
    if (repaintit) {
//        viewport()->repaint();
    }
}

/*!
    \fn tdesvnfilelist::slotDirItemDeleted(const TQString&)
 */
void tdesvnfilelist::slotDirItemDeleted(const TQString&what)
{
    m_pList->stopDirTimer();
    m_pList->m_fileTip->setItem(0);
    TQMap<TQString,TQChar>::Iterator it = m_pList->dirItems.find(what);
    if (it!=m_pList->dirItems.end() && m_pList->dirItems[what]=='A')  {
        m_pList->dirItems.erase(it);
    } else {
        m_pList->dirItems[what]='D';
    }
    m_pList->startDirTimer();
}


void tdesvnfilelist::gotPreview( const KFileItem*, const TQPixmap&)
{
#if 0
    FileListViewItem*which = findEntryItem(item->localPath());
    if (which) {
        which->setPreviewPix(pixmap);
    }
//    m_previewJob = 0;
//    if (m_svnitem || item != m_svnitem->fileItem()) return;

//    m_iconLabel -> setPixmap(pixmap);
#endif
}

void tdesvnfilelist::gotPreviewResult()
{
//    m_previewJob = 0;
}

FileListViewItem* tdesvnfilelist::findEntryItem(const TQString&what,FileListViewItem*startAt)
{
    if (!startAt && !what.startsWith(baseUri())) return 0;
    TQString _what = what;
    FileListViewItem*_s,*_temp;
    if (!startAt) {
        while (_what.endsWith("/")) {
            _what.truncate(_what.length()-1);
        }
        _s = static_cast<FileListViewItem*>(firstChild());
    } else {
        _s = static_cast<FileListViewItem*>(startAt->firstChild());
    }
    _temp = 0;
    while (_s) {
        if (_s->fullName()==_what) {
            return _s;
        }
        if (_what.startsWith(_s->fullName())) {
            _temp = findEntryItem(_what,_s);
            if (_temp) {
                return _temp;
            }
        }
        _s = static_cast<FileListViewItem*>(_s->nextSibling());
    }
    return 0;
}


/*!
    \fn tdesvnfilelist::contentsMouseMoveEvent( TQMouseEvent *e )
 */
void tdesvnfilelist::contentsMouseMoveEvent( TQMouseEvent *e )
{
    if (!m_pList->mousePressed)
    {
        if (Kdesvnsettings::display_file_tips()) {

            TQPoint vp = contentsToViewport( e->pos() );
            FileListViewItem*item = isExecuteArea( vp ) ? static_cast<FileListViewItem*>(itemAt( vp )) : 0L;

            if (item) {
                vp.setY( itemRect( item ).y() );
                TQRect rect( viewportToContents( vp ), TQSize(20, item->height()) );
                m_pList->m_fileTip->setItem( static_cast<SvnItem*>(item), rect, item->pixmap(0));
                m_pList->m_fileTip->setPreview(TDEGlobalSettings::showFilePreview(item->fullName())/*&&isWorkingCopy()*/
                        &&Kdesvnsettings::display_previews_in_file_tips());
                setShowToolTips(false);
            } else {
                m_pList->m_fileTip->setItem(0);
                setShowToolTips(true);
            }
        } else {
            m_pList->m_fileTip->setItem(0);
            setShowToolTips(true);
        }
    }
    else
    {
        if (( m_pList->presspos - e->pos() ).manhattanLength() > TQApplication::startDragDistance())
        {
            m_pList->m_fileTip->setItem(0);
            m_pList->mousePressed=false;
            //beginDrag();
        }
    }
    TDEListView::contentsMouseMoveEvent( e );
}

void tdesvnfilelist::contentsMousePressEvent(TQMouseEvent*e)
{
    TDEListView::contentsMousePressEvent(e);
    m_pList->m_fileTip->setItem(0);
    TQPoint p(contentsToViewport( e->pos()));
    TQListViewItem *i = itemAt( p );
    // this is from qt the example - hopefully I got my problems with drag&drop fixed.
    if ( i ) {
        // if the user clicked into the root decoration of the item, don't try to start a drag!
        if ( p.x() > header()->cellPos( header()->mapToActual( 0 ) ) +
                          treeStepSize() * ( i->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ||
             p.x() < header()->cellPos( header()->mapToActual( 0 ) ) )
        {
            m_pList->presspos = e->pos();
            m_pList->mousePressed = true;
        }
    }
}

void tdesvnfilelist::contentsMouseReleaseEvent(TQMouseEvent*e)
{
    TDEListView::contentsMouseReleaseEvent(e);
    m_pList->mousePressed = false;
}

/*!
    \fn tdesvnfilelist::contentsWheelEvent( TQWheelEvent * e )
 */
void tdesvnfilelist::contentsWheelEvent( TQWheelEvent * e )
{
   // when scrolling with mousewheel, stop possible pending filetip
   m_pList->m_fileTip->setItem(0);
   TDEListView::contentsWheelEvent( e );
}

void tdesvnfilelist::leaveEvent(TQEvent*e)
{
    m_pList->m_fileTip->setItem( 0 );
    TDEListView::leaveEvent( e );
}

void tdesvnfilelist::slotSettingsChanged()
{
    m_pList->m_fileTip->setOptions(!isNetworked()&&Kdesvnsettings::display_file_tips()&&
        TQToolTip::isGloballyEnabled(),true,6);
    if (m_pList->reReadSettings()) {
        refreshCurrentTree();
    } else {
        viewport()->repaint();
    }
    enableActions();
    sort();
    if (m_SvnWrapper && !m_SvnWrapper->doNetworking()) {
        m_SvnWrapper->stopFillCache();
    }
}


/*!
    \fn tdesvnfilelist::slotRelocate()
 */
void tdesvnfilelist::slotRelocate()
{
    if (!isWorkingCopy()) return;
    SvnItem*k = SelectedOrMain();
    if (!k) {
        KMessageBox::error(0,i18n("Error getting entry to relocate"));
        return;
    }
    TQString path,fromUrl;
    path = k->fullName();
    fromUrl = k->Url();
    CheckoutInfo_impl*ptr;
    KDialogBase * dlg = createDialog(&ptr,i18n("Relocate path %1").arg(path),true,"relocate_dlg");
    if (dlg) {
        ptr->setStartUrl(fromUrl);
        ptr->disableAppend(true);
        ptr->disableTargetDir(true);
        ptr->disableRange(true);
        ptr->disableOpen(true);
        ptr->disableExternals(true);
        ptr->hideDepth(true,true);
        bool done = false;
        dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),"relocate_dlg"));
        if (dlg->exec()==TQDialog::Accepted) {
            done = m_SvnWrapper->makeRelocate(fromUrl,ptr->reposURL(),path,ptr->overwrite());
        }
        dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"relocate_dlg",false);
        delete dlg;
        if (!done) return;
    }
    refreshItem(k->fItem());
}

void tdesvnfilelist::checkUnversionedDirs( FileListViewItem * _parent )
{
    TQDir d;
    if (_parent)
        d.setPath(_parent->fullName()); //FIXME: this one is not reliable, what if _parent == 0??
    //             else
    //                 d.setPath(this->firstChild()->fullName());

    d.setFilter( TQDir::Files | TQDir::Dirs );

    const TQFileInfoList *list = d.entryInfoList();
    if (!list) {
        return;
    }
    TQFileInfoListIterator nonversioned_it( *list );
    TQFileInfo *fi;

    svn::StatusEntries nonversioned_list;

    // FIXME: create a dlist and feed to insertDirs, mean while .. we are copying insertDirs since we weren't able to set svn_node_kind into appropriate value
    while ( (fi = nonversioned_it.current()) != 0 ) {
        if ((fi->fileName()!=".") && (fi->fileName()!="..")) {
            // trying to set entry->kind
//             svn_wc_status2_t wc_stat;
//             svn_wc_entry_t entry;
//             char *temp;
//             strcpy(temp, fi->fileName());
//             entry.name = temp;
//
//             wc_stat.entry = &entry;
//             if (fi->isDir())
//                 entry.kind = svn_node_dir;
//             else
//                 entry.kind = svn_node_file;
//
//             svn::Status stat(fi->fileName(), &wc_stat);

            svn::StatusPtr stat(new svn::Status(fi->absFilePath()));

            // start copying insertDirs
            FileListViewItem * item;
            if (!_parent) {
                item = new FileListViewItem(this, stat);
                kdDebug()<< "creating new FileListViewitem " + item->fullName() << endl;
            } else {
                item = new FileListViewItem(this,_parent, stat);
                kdDebug()<< "creating new FileListViewitem (with parent) " + item->fullName() << endl;
            }
            if (fi->isDir()) {
                m_Dirsread[item->fullName()]=false;
                item->setDropEnabled(true);
                if (isWorkingCopy()) {
                    m_pList->m_DirWatch->addDir(item->fullName());
                }
                kdDebug()<< "Watching folder: " + item->fullName() << endl;
            } else if (isWorkingCopy()) {
                m_pList->m_DirWatch->addFile(item->fullName());
                kdDebug()<< "Watching file: " + item->fullName() << endl;
            }
            // end of copying insertDirs

            nonversioned_list.append(stat);
            kdDebug() << "creating new FileListViewItem from TQDir entry: " << fi->fileName() << endl;
        }
        ++nonversioned_it;
    }

    // uncomment this if you've ben able to set svn_node_kind (see above)
    //this->insertDirs(_parent, nonversioned_list);
}

void tdesvnfilelist::rescanIconsRec(FileListViewItem*startAt,bool checkNewer,bool no_update)
{
    FileListViewItem*_s;
    if (!startAt) {
        _s = static_cast<FileListViewItem*>(firstChild());
    } else {
        _s = static_cast<FileListViewItem*>(startAt->firstChild());
    }
    if (!_s) {
        return;
    }
    svn::SharedPointer<svn::Status> d;
    while (_s) {
        //_s->makePixmap();

        if (!no_update) {
            if (m_SvnWrapper->getUpdated(_s->stat()->path(),d) && d) {
                _s->updateStatus(d);
            } else {
                _s->update();
            }
        }
        rescanIconsRec(_s,checkNewer,no_update);
        if (checkNewer && _s->isDir() && _s->isOpen()) {
            svn::StatusEntries target;
            m_SvnWrapper->getaddedItems(_s->stat()->path(),target);
            insertDirs(_s,target);
        }
        _s = static_cast<FileListViewItem*>(_s->nextSibling());
    }
}

void tdesvnfilelist::slotRescanIcons(bool checkNewer)
{
    rescanIconsRec(0L,checkNewer);
}


/*!
    \fn tdesvnfilelist::slotCheckNewItems()
 */
void tdesvnfilelist::slotCheckNewItems()
{
    if (!isWorkingCopy()) {
        KMessageBox::sorry(0,i18n("Only in working copy possible."),i18n("Error"));
        return;
    }
    if (allSelected()->count()>1) {
        KMessageBox::sorry(0,i18n("Only on single folder possible"),i18n("Error"));
        return;
    }
    SvnItem*w = SelectedOrMain();
    if (!w) {
        KMessageBox::sorry(0,i18n("Sorry - internal error!"),i18n("Error"));
        return;
    }
    m_SvnWrapper->checkAddItems(w->fullName(),true);
}

/*!
    \fn tdesvnfilelist::slotMakeRangeLog()
 */
void tdesvnfilelist::slotMakeRangeLog()
{
    TQString what;
    SvnItem*k = SelectedOrMain();
    if (k) {
        what = k->fullName();
    } else if (!isWorkingCopy() && allSelected()->count()==0){
        what = baseUri();
    } else {
        return;
    }
    Rangeinput_impl*rdlg;
    KDialogBase*dlg = createDialog(&rdlg,TQString(i18n("Revisions")),true,"revisions_dlg");
    if (!dlg) {
        return;
    }
    bool list = Kdesvnsettings::self()->log_always_list_changed_files();
    int i = dlg->exec();
    if (i==TQDialog::Accepted) {
        Rangeinput_impl::revision_range r = rdlg->getRange();
        m_SvnWrapper->makeLog(r.first,r.second,(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision), what,list,0);
    }
    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false);
}


void tdesvnfilelist::slotMakeTree()
{
    TQString what;
    SvnItem*k = SelectedOrMain();
    if (k) {
        what = k->fullName();
    } else if (!isWorkingCopy() && allSelected()->count()==0){
        what = baseUri();
    } else {
        return;
    }
    svn::Revision rev(isWorkingCopy()?svn::Revision::WORKING:m_pList->m_remoteRevision);

    m_SvnWrapper->makeTree(what,rev);
}

void tdesvnfilelist::slotMakePartTree()
{
    TQString what;
    SvnItem*k = SelectedOrMain();
    if (k) {
        what = k->fullName();
    } else if (!isWorkingCopy() && allSelected()->count()==0){
        what = baseUri();
    } else {
        return;
    }
    Rangeinput_impl*rdlg;
    KDialogBase*dlg = createDialog(&rdlg,TQString(i18n("Revisions")),true,"revisions_dlg");
    if (!dlg) {
        return;
    }
    int i = dlg->exec();
    Rangeinput_impl::revision_range r;
    if (i==TQDialog::Accepted) {
        r = rdlg->getRange();
    }
    dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false);

    if (i==TQDialog::Accepted) {
        svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision);
        m_SvnWrapper->makeTree(what,rev,r.first,r.second);
    }
}

/*!
    \fn tdesvnfilelist::slotMakeLog()
 */
void tdesvnfilelist::slotMakeLog()
{
    TQString what;
    SvnItem*k = SelectedOrMain();
    if (k) {
        what = k->fullName();
    } else if (!isWorkingCopy() && allSelected()->count()==0){
        what = baseUri();
    } else {
        return;
    }
    // yes! so if we have a limit, the limit counts from HEAD
    // not from START
    svn::Revision start(svn::Revision::HEAD);
    if (!isWorkingCopy()) {
        start=m_pList->m_remoteRevision;
    }
    svn::Revision end(svn::Revision::START);
    bool list = Kdesvnsettings::self()->log_always_list_changed_files();
    int l = Kdesvnsettings::self()->maximum_displayed_logs();
    m_SvnWrapper->makeLog(start,end,(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision),what,list,l);
}

const svn::Revision& tdesvnfilelist::remoteRevision()const
{
    return m_pList->m_remoteRevision;
}


/*!
    \fn tdesvnfilelist::slotOpenWith()
 */
void tdesvnfilelist::slotOpenWith()
{
    FileListViewItem* which = singleSelected();
    if (!which||which->isDir()) {
        return;
    }
    svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision);
    KURL::List lst;
    lst.append(which->kdeName(rev));
    KRun::displayOpenWithDialog(lst);
}

void tdesvnfilelist::slotUnfoldTree()
{
    StopSimpleDlg sdlg(0,0,i18n("Unfold tree"),i18n("Unfold all folder"));

    connect(this,TQT_SIGNAL(sigListError()),
            &sdlg,TQT_SLOT(makeCancel()));

    TQListViewItemIterator it(this);
    TQTime t;t.start();

    setUpdatesEnabled(false);
    {
        WidgetBlockStack a(this);
        while (TQListViewItem* item = it.current())
        {
            if (item->isExpandable()) {
                if (sdlg.isCanceld()) {
                    m_SvnWrapper->slotCancel(true);
                    break;
                }
                if (t.elapsed()>=200) {
                    sdlg.slotTick();
                    kapp->processEvents(20);
                    t.restart();
                }
                ((FileListViewItem*)item)->setOpenNoBlock(true);
            }
            ++it;
        }
    }
    setFocus();
    setUpdatesEnabled(true);
    viewport()->repaint();
    repaint();
    m_SvnWrapper->slotCancel(false);
}

void tdesvnfilelist::slotFoldTree()
{
    TQListViewItemIterator it(this);
    while (TQListViewItem* item = it.current())
    {
        // don't close the top level directory
        if (item->isExpandable() && item->parent())
            item->setOpen(false);

        ++it;
    }
}

/*!
    \fn tdesvnfilelist::uniqueSelected()
 */
bool tdesvnfilelist::uniqueTypeSelected()
{
    FileListViewItemList*ls = allSelected();
    FileListViewItemListIterator it(*ls);
    FileListViewItem*cur=it.current();
    if (!cur) {
        return false;
    }
    bool dir = cur->isDir();
    while ( (cur=it.current())!=0) {
        ++it;
        if (cur->isDir()!=dir) {
            return false;
        }
    }
    return true;
}

void tdesvnfilelist::slotChangeProperties(const svn::PropertiesMap&pm,const TQValueList<TQString>&dellist,const TQString&path)
{
    m_SvnWrapper->changeProperties(pm,dellist,path);
    FileListViewItem* which = singleSelected();
    kdDebug()<<(which?which->fullName():"nix") << " -> " << path<<endl;
    if (which && which->fullName()==path) {
        which->refreshStatus();
        refreshCurrent(which);
        _propListTimeout();
    }
}

void tdesvnfilelist::slotUpdateLogCache()
{
    if (baseUri().length()>0 && m_SvnWrapper->doNetworking()) {
        TDEAction*temp = filesActions()->action("update_log_cache");

        if (!m_SvnWrapper->threadRunning(SvnActions::fillcachethread)) {
            m_SvnWrapper->startFillCache(baseUri());
            if (temp) {
                temp->setText(i18n("Stop updating the logcache"));
            }
        } else {
            m_SvnWrapper->stopFillCache();
            if (temp) {
                temp->setText(i18n("Update log cache"));
            }
        }
    }
}

#include "tdesvnfilelist.moc"
