diff options
Diffstat (limited to 'src/svnfrontend/kdesvnfilelist.cpp')
-rw-r--r-- | src/svnfrontend/kdesvnfilelist.cpp | 3160 |
1 files changed, 3160 insertions, 0 deletions
diff --git a/src/svnfrontend/kdesvnfilelist.cpp b/src/svnfrontend/kdesvnfilelist.cpp new file mode 100644 index 0000000..d9116cb --- /dev/null +++ b/src/svnfrontend/kdesvnfilelist.cpp @@ -0,0 +1,3160 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 by Rajko Albrecht * + * [email protected] * + * * + * 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 "kdesvnfilelist.h" +#include "kdesvn_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 "src/settings/kdesvnsettings.h" +#include "src/svnqt/revision.hpp" +#include "src/svnqt/dirent.hpp" +#include "src/svnqt/client.hpp" +#include "src/svnqt/status.hpp" +#include "src/svnqt/url.hpp" +#include "helpers/sshagent.h" +#include "helpers/sub2qt.h" +#include "fronthelpers/cursorstack.h" +#include "fronthelpers/widgetblockstack.h" + +#include <kapplication.h> +#include <kiconloader.h> +#include <kdirwatch.h> +#include <klocale.h> +#include <kactioncollection.h> +#include <kshortcut.h> +#include <kmessagebox.h> +#include <kdirselectdialog.h> +#include <klineedit.h> +#include <kfileitem.h> +#include <kdialog.h> +#include <kfiledialog.h> +#include <kdebug.h> +#include <kurldrag.h> +#include <ktempfile.h> +#include <kio/job.h> +#include <krun.h> +#include <kurldrag.h> +#include <ktrader.h> + +#include <qvbox.h> +#include <qpainter.h> +#include <qstyle.h> +#include <qapplication.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qtooltip.h> +#include <qregexp.h> +#include <qpopupmenu.h> +#include <qcursor.h> +#include <qheader.h> +#include <qcheckbox.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; + }; + QListViewItem *dragOverItem; + QPoint dragOverPoint; + QRect 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; + QString intern_drop_target,merge_Src1, merge_Src2,merge_Target; + QDropEvent::Action intern_drop_action; + QPoint intern_drop_pos; + QTimer drop_timer; + QTimer dirwatch_timer; + QTimer propTimer; + + bool mousePressed; + QPoint presspos; + + QMap<QString,QChar> dirItems; + + void stopDirTimer() + { + dirwatch_timer.stop(); + } + + void startDirTimer() + { + dirwatch_timer.start(250,true); + } + + void connectDirTimer(QObject*ob) + { + QObject::connect(&dirwatch_timer,SIGNAL(timeout()),ob,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(QObject*ob) + { + QObject::connect(&propTimer,SIGNAL(timeout()),ob,SLOT(_propListTimeout())); + } + +private: + void readSettings(); +}; + +KdesvnFileListPrivate::KdesvnFileListPrivate() + : dragOverItem(0),dragOverPoint(QPoint(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); +} + +kdesvnfilelist::kdesvnfilelist(KActionCollection*aCollect,QWidget *parent, const char *name) + : KListView(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()&& + QToolTip::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,SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),this, + SLOT(slotContextMenuRequested(QListViewItem *, const QPoint &, int))); + + /* not via executed 'cause click may used for selection - single click execution + just confuses in an application */ + connect(this,SIGNAL(doubleClicked(QListViewItem*)),this,SLOT(slotItemDoubleClicked(QListViewItem*))); + connect(this,SIGNAL(returnPressed(QListViewItem*)),this,SLOT(slotItemDoubleClicked(QListViewItem*))); + + connect(this,SIGNAL(selectionChanged()),this,SLOT(slotSelectionChanged())); + connect(m_SvnWrapper,SIGNAL(clientException(const QString&)),this,SLOT(slotClientException(const QString&))); + connect(m_SvnWrapper,SIGNAL(sendNotify(const QString&)),this,SLOT(slotNotifyMessage(const QString&))); + connect(m_SvnWrapper,SIGNAL(reinitItem(SvnItem*)),this,SLOT(slotReinitItem(SvnItem*))); + connect(m_SvnWrapper,SIGNAL(sigRefreshAll()),this,SLOT(refreshCurrentTree())); + connect(m_SvnWrapper,SIGNAL(sigRefreshCurrent(SvnItem*)),this,SLOT(refreshCurrent(SvnItem*))); + connect(m_SvnWrapper,SIGNAL(sigRefreshIcons(bool)),this,SLOT(slotRescanIcons(bool))); + connect(this,SIGNAL(dropped (QDropEvent*,QListViewItem*)), + this,SLOT(slotDropped(QDropEvent*,QListViewItem*))); + connect(m_SvnWrapper,SIGNAL(sigGotourl(const QString&)),this,SLOT(_openURL(const QString&))); + + connect(m_SvnWrapper,SIGNAL(sigCacheStatus(Q_LONG,Q_LONG)),this,SIGNAL(sigCacheStatus(Q_LONG,Q_LONG))); + connect(m_SvnWrapper,SIGNAL(sigThreadsChanged()),this,SLOT(enableActions())); + + m_pList->connectDirTimer(this); + m_pList->connectPropTimer(this); + + setDropHighlighter(true); + setDragEnabled(true); + setItemsMovable(true); + setDropVisualizer(false); + setAcceptDrops(true); +} + +svn::Client*kdesvnfilelist::svnclient() +{ + return m_SvnWrapper->svnclient(); +} + +void kdesvnfilelist::setupActions() +{ + if (!m_filesAction) return; + KAction*tmp_action; + /* local and remote actions */ + /* 1. actions on dirs AND files */ + //new KAction(i18n("Log..."),"kdesvnlog",KShortcut(SHIFT+CTRL+Key_L),this,SLOT(slotMakeRangeLog()),m_filesAction,"make_svn_log"); + new KAction(i18n("Full Log"),"kdesvnlog",KShortcut(CTRL+Key_L),this,SLOT(slotMakeLog()),m_filesAction,"make_svn_log_full"); + new KAction(i18n("Full revision tree"),"kdesvnlog",KShortcut(CTRL+Key_T),this,SLOT(slotMakeTree()),m_filesAction,"make_svn_tree"); + new KAction(i18n("Partial revision tree"),"kdesvnlog",KShortcut(SHIFT+CTRL+Key_T), + this,SLOT(slotMakePartTree()),m_filesAction,"make_svn_partialtree"); + + new KAction(i18n("Properties"),"edit", + KShortcut(CTRL+Key_P),m_SvnWrapper,SLOT(slotProperties()),m_filesAction,"make_svn_property"); + new KAction(i18n("Display Properties"),"edit", + KShortcut(SHIFT+CTRL+Key_P),this,SLOT(slotDisplayProperties()),m_filesAction,"get_svn_property"); + + tmp_action = new KAction(i18n("Display last changes"),"kdesvndiff", + KShortcut(),this,SLOT(slotDisplayLastDiff()),m_filesAction,"make_last_change"); + tmp_action->setToolTip(i18n("Display last changes as difference to previous commit.")); + + m_InfoAction = new KAction(i18n("Details"),"kdesvninfo", + KShortcut(CTRL+Key_I),this,SLOT(slotInfo()),m_filesAction,"make_svn_info"); + m_RenameAction = new KAction(i18n("Move"),"move", + KShortcut(Key_F2),this,SLOT(slotRename()),m_filesAction,"make_svn_rename"); + m_CopyAction = new KAction(i18n("Copy"),"kdesvncopy", + KShortcut(CTRL+Key_C),this,SLOT(slotCopy()),m_filesAction,"make_svn_copy"); + tmp_action = new KAction(i18n("Check for updates"),"kdesvncheckupdates",KShortcut(),this,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 KAction(i18n("Blame"),"kdesvnblame", + KShortcut(),this,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 KAction(i18n("Blame range"),"kdesvnblame", + KShortcut(),this,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 KAction(i18n("Cat head"), "kdesvncat", + KShortcut(),this,SLOT(slotCat()),m_filesAction,"make_svn_cat"); + m_CatAction->setToolTip(i18n("Output the content of specified files or URLs.")); + tmp_action = new KAction(i18n("Cat revision..."),"kdesvncat", + KShortcut(),this,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 KAction(i18n("Lock current items"),"kdesvnlock", + KShortcut(),this,SLOT(slotLock()),m_filesAction,"make_svn_lock"); + m_UnlockAction = new KAction(i18n("Unlock current items"),"kdesvnunlock", + KShortcut(),this,SLOT(slotUnlock()),m_filesAction,"make_svn_unlock"); + + /* 3. actions only on dirs */ + m_MkdirAction = new KAction(i18n("New folder"),"folder_new", + KShortcut(),this,SLOT(slotMkdir()),m_filesAction,"make_svn_mkdir"); + m_switchRepository = new KAction(i18n("Switch repository"),"kdesvnswitch", + KShortcut(), m_SvnWrapper,SLOT(slotSwitch()),m_filesAction,"make_svn_switch"); + m_switchRepository->setToolTip(i18n("Switch repository path of current working copy path (\"svn switch\")")); + tmp_action = new KAction(i18n("Relocate current working copy url"),"kdesvnrelocate",KShortcut(), + this,SLOT(slotRelocate()),m_filesAction,"make_svn_relocate"); + tmp_action->setToolTip(i18n("Relocate url of current working copy path to other url")); + tmp_action = new KAction(i18n("Check for unversioned items"),"kdesvnaddrecursive",KShortcut(), + this,SLOT(slotCheckNewItems()),m_filesAction,"make_check_unversioned"); + tmp_action->setToolTip(i18n("Browse folder for unversioned items and add them if wanted.")); + + m_changeToRepository = new KAction(i18n("Open repository of working copy"),"gohome",KShortcut(), + this,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 KAction(i18n("Cleanup"),"kdesvncleanup", + KShortcut(),this,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 KAction(i18n("Import folders into current"),"fileimport",KShortcut(), + this,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 KAction(i18n("Add selected files/dirs"), + "kdesvnadd",KShortcut(Key_Insert),m_SvnWrapper,SLOT(slotAdd()),m_filesAction,"make_svn_add"); + m_AddCurrent->setToolTip(i18n("Adding selected files and/or directories to repository")); + tmp_action = new KAction("Add selected files/dirs recursive", + "kdesvnaddrecursive",KShortcut(CTRL+Key_Insert),m_SvnWrapper,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 KAction(i18n("Delete selected files/dirs"),"kdesvndelete", + KShortcut(Key_Delete),this,SLOT(slotDelete()),m_filesAction,"make_svn_remove"); + m_DelCurrent->setToolTip(i18n("Deleting selected files and/or directories from repository")); + m_RevertAction = new KAction(i18n("Revert current changes"),"revert", + KShortcut(),m_SvnWrapper,SLOT(slotRevert()),m_filesAction,"make_svn_revert"); + + m_ResolvedAction = new KAction(i18n("Mark resolved"),KShortcut(), + this,SLOT(slotResolved()),m_filesAction,"make_resolved"); + m_ResolvedAction->setToolTip(i18n("Marking files or dirs resolved")); + + tmp_action = new KAction(i18n("Resolve conflicts"),KShortcut(), + this,SLOT(slotTryResolve()),m_filesAction,"make_try_resolve"); + + m_IgnoreAction = new KAction(i18n("Ignore/Unignore current item"),KShortcut(),this,SLOT(slotIgnore()),m_filesAction,"make_svn_ignore"); + + m_UpdateHead = new KAction(i18n("Update to head"),"kdesvnupdate", + KShortcut(),m_SvnWrapper,SLOT(slotUpdateHeadRec()),m_filesAction,"make_svn_headupdate"); + m_UpdateRev = new KAction(i18n("Update to revision..."),"kdesvnupdate", + KShortcut(),m_SvnWrapper,SLOT(slotUpdateTo()),m_filesAction,"make_svn_revupdate"); + m_commitAction = new KAction(i18n("Commit"),"kdesvncommit", + KShortcut("CTRL+#"),m_SvnWrapper,SLOT(slotCommit()),m_filesAction,"make_svn_commit"); + + tmp_action = new KAction(i18n("Diff local changes"),"kdesvndiff", + KShortcut(CTRL+Key_D),this,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 KAction(i18n("Diff against HEAD"),"kdesvndiff", + KShortcut(CTRL+Key_H),this,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 KAction(i18n("Diff items"),"kdesvndiff", + KShortcut(),this,SLOT(slotDiffPathes()),m_filesAction,"make_svn_itemsdiff"); + tmp_action->setToolTip(i18n("Diff two items")); + + + m_MergeRevisionAction = new KAction(i18n("Merge two revisions"),"kdesvnmerge", + KShortcut(),this,SLOT(slotMergeRevisions()),m_filesAction,"make_svn_merge_revisions"); + m_MergeRevisionAction->setToolTip(i18n("Merge two revisions of this entry into itself")); + + tmp_action=new KAction(i18n("Merge..."),"kdesvnmerge", + KShortcut(),this,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 KAction( i18n( "Open With..." ), 0, this, SLOT( slotOpenWith() ), m_filesAction, "openwith" ); + + /* remote actions only */ + m_CheckoutCurrentAction = new KAction(i18n("Checkout current repository path"),"kdesvncheckout",KShortcut(), + m_SvnWrapper,SLOT(slotCheckoutCurrent()),m_filesAction,"make_svn_checkout_current"); + m_ExportCurrentAction = new KAction(i18n("Export current repository path"),"kdesvnexport",KShortcut(), + m_SvnWrapper,SLOT(slotExportCurrent()),m_filesAction,"make_svn_export_current"); + new KAction(i18n("Select browse revision"),KShortcut(),this,SLOT(slotSelectBrowsingRevision()),m_filesAction,"switch_browse_revision"); + + /* independe actions */ + m_CheckoutAction = new KAction(i18n("Checkout a repository"),"kdesvncheckout", + KShortcut(),m_SvnWrapper,SLOT(slotCheckout()),m_filesAction,"make_svn_checkout"); + m_ExportAction = new KAction(i18n("Export a repository"),"kdesvnexport", + KShortcut(),m_SvnWrapper,SLOT(slotExport()),m_filesAction,"make_svn_export"); + m_RefreshViewAction = new KAction(i18n("Refresh view"),"reload",KShortcut(Key_F5),this,SLOT(refreshCurrentTree()),m_filesAction,"make_view_refresh"); + + new KAction(i18n("Diff revisions"),"kdesvndiff",KShortcut(),this,SLOT(slotDiffRevisions()),m_filesAction,"make_revisions_diff"); + + /* folding options */ + tmp_action = new KAction( i18n("Unfold File Tree"), 0, this , SLOT(slotUnfoldTree()), m_filesAction, "view_unfold_tree" ); + tmp_action->setToolTip(i18n("Opens all branches of the file tree")); + tmp_action = new KAction( i18n("Fold File Tree"), 0, this, SLOT(slotFoldTree()), m_filesAction, "view_fold_tree" ); + tmp_action->setToolTip(i18n("Closes all branches of the file tree")); + + /* caching */ + tmp_action = new KAction( i18n("Update log cache"),0,this,SLOT(slotUpdateLogCache()),m_filesAction,"update_log_cache" ); + tmp_action->setToolTip(i18n("Update the log cache for current repository")); + /* tmp_action = new KAction( i18n("Stop update log cache"),0,this,SLOT(slotUpdateLogCache()),m_filesAction,"stop_update_log_cache" ); + tmp_action->setToolTip(i18n("Stop the update of the log cache")); + */ + + enableActions(); + m_filesAction->setHighlightingEnabled(true); +} + +KActionCollection*kdesvnfilelist::filesActions() +{ + return m_filesAction; +} + +FileListViewItemList* kdesvnfilelist::allSelected() +{ + if (!m_SelectedItems) { + m_SelectedItems = new FileListViewItemList; + } + return m_SelectedItems; +} + +void kdesvnfilelist::SelectionList(SvnItemList*target) +{ + if (!m_SelectedItems||!target) return; + FileListViewItemListIterator iter(*m_SelectedItems); + FileListViewItem*cur; + while ( (cur=iter.current())!=0) { + ++iter; + target->append(cur); + } +} + +SvnItem*kdesvnfilelist::SelectedOrMain() +{ + if (singleSelected()!=0) { + return singleSelected(); + } + if (isWorkingCopy()&&firstChild()) { + return static_cast<FileListViewItem*>(firstChild()); + } + return 0; +} + +KURL::List kdesvnfilelist::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 KIO urls */ + lst.append(cur->kdeName(m_pList->m_remoteRevision)); + } + return lst; +} + +QWidget*kdesvnfilelist::realWidget() +{ + return this; +} + +FileListViewItem* kdesvnfilelist::singleSelected() +{ + if (m_SelectedItems && m_SelectedItems->count()==1) { + return m_SelectedItems->at(0); + } + return 0; +} + +SvnItem*kdesvnfilelist::Selected() +{ + return singleSelected(); +} + +void kdesvnfilelist::_openURL(const QString&url) +{ + openURL(url,true); + emit sigUrlChanged(baseUri()); +} + +bool kdesvnfilelist::openURL( const KURL &url,bool noReinit ) +{ + CursorStack a; + m_SvnWrapper->killallThreads(); + clear(); + emit sigProplist(svn::PathPropertiesMapListPtr(new svn::PathPropertiesMapList()),false,QString("")); + 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(); + + QString query = url.query(); + + KURL _url = url; + QString proto = svn::Url::transformProtokoll(url.protocol()); + _url.cleanPath(true); + _url.setProtocol(proto); + proto = _url.url(-1); + + QStringList s = QStringList::split("?",proto); + if (s.size()>1) { + setBaseUri(s[0]); + } else { + setBaseUri(proto); + } + setWorkingCopy(false); + setNetworked(false); + + m_pList->m_remoteRevision=svn::Revision::HEAD; + + + QString _dummy; + + if (!QString::compare("svn+file",url.protocol())) { + setBaseUri("file://"+url.path()); + } else { + if (url.isLocalFile()) { + QString s = url.path(); + while(s.endsWith("/")) { + s.remove(s.length()-1,1); + } + QFileInfo fi(s); + if (fi.exists() && fi.isSymLink()) { + QString 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) { + QMap<QString,QString> q = url.queryItems(); + if (q.find("rev")!=q.end()) { + QString 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(this); + connect(m_pList->m_DirWatch,SIGNAL(dirty(const QString&)),this,SLOT(slotDirItemDirty(const QString&))); + connect(m_pList->m_DirWatch,SIGNAL(created(const QString&)),this,SLOT(slotDirItemCreated(const QString&))); + connect(m_pList->m_DirWatch,SIGNAL(deleted(const QString&)),this,SLOT(slotDirItemDeleted(const QString&))); + /* 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()&& + QToolTip::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); + QTimer::singleShot(1,this,SLOT(readSupportData())); + enableActions(); + return result; +} + +void kdesvnfilelist::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 kdesvnfilelist::checkDirs(const QString&_what,FileListViewItem * _parent) +{ + QString 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 QDir and create new filelistviewitem + checkUnversionedDirs(_parent); + } + + if ((*it)->path()==what||QString::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 kdesvnfilelist::insertDirs(FileListViewItem * _parent,svn::StatusEntries&dlist) +{ + svn::StatusEntries::iterator it; +#if 0 + KFileItemList oneItem; +#endif + + QTime _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 kdesvnfilelist::slotDirAdded(const QString&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; + } + QListViewItem*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()); + } +} + +kdesvnfilelist::~kdesvnfilelist() +{ + delete m_pList; + delete m_SelectedItems; + SshAgent ssh; + ssh.killSshAgent(); +} + +void kdesvnfilelist::slotItemRead(QListViewItem*aItem) +{ + if (!aItem) return; + CursorStack a(Qt::BusyCursor); + FileListViewItem* k = static_cast<FileListViewItem*>( aItem ); + bool _ex = true; + if (isWorkingCopy()) { + QDir 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 kdesvnfilelist::slotReinitItem(SvnItem*item) +{ + if (!item) { + kdDebug()<<"kdesvnfilelist::slotReinitItem(SvnItem*item): item == null" << endl; + return; + } + FileListViewItem*k = item->fItem(); + if (!k) { + kdDebug()<<"kdesvnfilelist::slotReinitItem(SvnItem*item): k == null" << endl; + } + refreshItem(k); + if (!k) { + return; + } + if (k->isDir()) { + k->removeChilds(); + m_Dirsread[k->fullName()]=false;; + } +} + +void kdesvnfilelist::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(); + KAction * 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->authorizeKAction("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 kdesvnfilelist::slotSelectionChanged() +{ + m_pList->stopProptimer(); + if (m_SelectedItems==0) { + m_SelectedItems = new FileListViewItemList; + m_SelectedItems->setAutoDelete(false); + } + m_SelectedItems->clear(); + + QListViewItemIterator it( this, QListViewItemIterator::Selected ); + while ( it.current() ) { + m_SelectedItems->append( static_cast<FileListViewItem*>(it.current()) ); + ++it; + } + enableActions(); + m_pList->startProptimer(); +} + +/*! + \fn kdesvnfilelist::slotClientException(const QString&) + */ +void kdesvnfilelist::slotClientException(const QString&what) +{ + emit sigLogMessage(what); + KMessageBox::sorry(KApplication::activeModalWidget(),what,i18n("SVN Error")); +} + + +/*! + \fn kdesvnfilelist::slotNotifyMessage(const QString&) + */ +void kdesvnfilelist::slotNotifyMessage(const QString&what) +{ + emit sigLogMessage(what); + kapp->processEvents(20); +} + +void kdesvnfilelist::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(KApplication::activeModalWidget(),i18n("Could not retrieve repository of working copy."),i18n("SVN Error")); + } else { + sigSwitchUrl(i.reposRoot()); + } +} + +void kdesvnfilelist::slotItemDoubleClicked(QListViewItem*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); + QString feditor = Kdesvnsettings::external_display(); + if ( feditor.compare("default") == 0 ) { + KURL::List lst; + lst.append(fki->kdeName(rev)); + KTrader::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 kdesvnfilelist::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 kdesvnfilelist::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 kdesvnfilelist::slotTryResolve() +{ + if (!isWorkingCopy()) return; + FileListViewItem*which= singleSelected(); + if (!which || which->isDir()) { + return; + } + m_SvnWrapper->slotResolve(which->fullName()); +} + +template<class T> KDialogBase* kdesvnfilelist::createDialog(T**ptr,const QString&_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( + KApplication::activeModalWidget(), + name, + true, + _head, + buttons); + + if (!dlg) return dlg; + QWidget* Dialog1Layout = dlg->makeVBoxMainWidget(); + *ptr = new T(Dialog1Layout); + dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),name?name:"standard_size")); + return dlg; +} + +void kdesvnfilelist::slotImportDirsIntoCurrent() +{ + slotImportIntoCurrent(true); +} + +/*! + \fn kdesvnfilelist::slotImportIntoCurrent() + */ +void kdesvnfilelist::slotImportIntoCurrent(bool dirs) +{ + if (allSelected()->count()>1) { + KMessageBox::error(this,i18n("Cannot import into multiple targets!")); + return; + } + QString targetUri; + if (allSelected()->count()==0) { + targetUri=baseUri(); + } else { + targetUri = allSelected()->at(0)->Url(); + } + KURL uri; + if (dirs) uri = KFileDialog::getExistingDirectory(QString::null,this,"Import files from folder"); + else uri = KFileDialog::getImageOpenURL(QString::null,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 kdesvnfilelist::slotImportIntoDir(const KURL&importUrl,const QString&target,bool dirs) +{ + Logmsg_impl*ptr; + Importdir_logmsg*ptr2 = 0; + + KDialogBase*dlg; + KURL uri = importUrl; + QString targetUri = target; + while (targetUri.endsWith("/")) { + targetUri.truncate(targetUri.length()-1); + } + + if (dirs) { + dlg = createDialog(&ptr2,QString(i18n("Import log")),true,"import_log_msg"); + ptr = ptr2; + ptr2->createDirboxDir("\""+uri.fileName(true)+"\""); + } else { + dlg = createDialog(&ptr,QString(i18n("Import log")),true,"import_log_msg"); + } + + if (!dlg) return; + + ptr->initHistory(); + if (dlg->exec()!=QDialog::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); + + QString logMessage = ptr->getMessage(); + svn::Depth rec = ptr->getDepth(); + ptr->saveHistory(false); + uri.setProtocol(""); + QString 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 kdesvnfilelist::readSupportData() +{ + /// this moment empty cause no usagedata explicit used by kdesvnfilelist +} + +void kdesvnfilelist::refreshCurrentTree() +{ + QTime 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(); + QTimer::singleShot(1,this,SLOT(readSupportData())); + //m_pList->startScan(); +} + +void kdesvnfilelist::refreshCurrent(SvnItem*cur) +{ + if (!cur||!cur->fItem()) { + refreshCurrentTree(); + return; + } + kapp->processEvents(); + setUpdatesEnabled(false); + refreshRecursive(cur->fItem()); + setUpdatesEnabled(true); + viewport()->repaint(); +} + +bool kdesvnfilelist::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()); + } + + QString 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(); + QListViewItemIterator qlvit( this, QListViewItemIterator::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; +} + +KTrader::OfferList kdesvnfilelist::offersList(SvnItem*item,bool execOnly) +{ + KTrader::OfferList offers; + if (!item) { + return offers; + } + QString constraint; + if (execOnly) { + constraint = "Type == 'Application' or (exist Exec)"; + } else { + constraint = "Type == 'Application'"; + } + offers = KTrader::self()->query(item->mimeType()->name(), constraint); + + return offers; +} + +void kdesvnfilelist::slotContextMenuRequested(QListViewItem */* _item */, const QPoint &, int) +{ +// FileListViewItem*item = static_cast<FileListViewItem*>(_item); + bool isopen = baseUri().length()>0; + SvnItemList l; + SelectionList(&l); + + QString 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"; + } + } + + QWidget * target; + emit sigShowPopup(menuname,&target); + QPopupMenu *popup = static_cast<QPopupMenu *>(target); + if (!popup) { + kdDebug()<<"Error getting popupMenu"<<endl; + return; + } + + KTrader::OfferList offers; + OpenContextmenu*me=0; + KAction*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(QCursor::pos()); + if (id>-1) { + popup->removeItem(id); + } + delete me; + if (temp) { + temp->unplug(popup); + } +} + +/** +* Overridden virtuals for Qt drag 'n drop (XDND) +*/ +void kdesvnfilelist::contentsDragEnterEvent(QDragEnterEvent *event) +{ + QListViewItem*item; + bool ok = validDropEvent(event,item); + if (ok) { + event->accept(); + } else { + event->ignore(); + } +} + +//void kdesvnfilelist::startDrag() +QDragObject* kdesvnfilelist::dragObject() +{ + m_pList->m_fileTip->setItem(0); + QListViewItem * m_pressedItem = currentItem(); + if (!m_pressedItem) { + return 0; + } + QPixmap 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 : kdesvnPartFactory::instance()->iconLoader()->currentSize( KIcon::Small ); // Default = small + pixmap2 = DesktopIcon( "kmultiple", 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()) { + QStrList l; + QString t; + KURL::List::ConstIterator it = urls.begin(); + for (;it!=urls.end();++it) { + l.append((*it).prettyURL()); + } + drag->setUris(l); + } + + drag->setExportAsText(true); + if ( !pixmap2.isNull() ) + drag->setPixmap( pixmap2 ); + else if ( !pixmap0Invalid ) + drag->setPixmap( *m_pressedItem->pixmap( 0 ) ); + + return drag; +} + +void kdesvnfilelist::contentsDragLeaveEvent( QDragLeaveEvent * ) +{ + cleanHighLighter(); +} + +bool kdesvnfilelist::acceptDrag(QDropEvent *event)const +{ + return KURLDrag::canDecode(event); +} + +bool kdesvnfilelist::validDropEvent(QDropEvent*event,QListViewItem*&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 { + QPoint 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 kdesvnfilelist::contentsDropEvent(QDropEvent * event) +{ + QListViewItem *item = 0; + bool ok = validDropEvent(event,item); + cleanHighLighter(); + if (ok) { + dropped(event,item); + } else { + event->ignore(); + } +} + +void kdesvnfilelist::contentsDragMoveEvent( QDragMoveEvent* event) +{ + QListViewItem * item; + bool ok = validDropEvent(event,item); + + if (item && item!=m_pList->dragOverItem) { + QPoint vp = contentsToViewport( event->pos() ); + m_pList->dragOverItem=item; + m_pList->dragOverPoint = vp; + QRect 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 kdesvnfilelist::viewportPaintEvent(QPaintEvent *ev) +{ + KListView::viewportPaintEvent(ev); + if (m_pList->mOldDropHighlighter.isValid() && ev->rect().intersects(m_pList->mOldDropHighlighter)) { + QPainter painter(viewport()); + style().drawPrimitive(QStyle::PE_FocusRect, &painter, m_pList->mOldDropHighlighter, colorGroup(), + QStyle::Style_FocusAtBorder); + } +} + +void kdesvnfilelist::cleanHighLighter() +{ + if (m_pList->mOldDropHighlighter.isValid()) { + QRect rect=m_pList->mOldDropHighlighter; + m_pList->mOldDropHighlighter=QRect(); + viewport()->repaint(rect, true); + } +} + +/*! + \fn kdesvnfilelist::slotMergeRevisions() + */ +void kdesvnfilelist::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 kdesvnfilelist::slotMerge() +{ + FileListViewItem*which= singleSelected(); + QString 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,QString(i18n("Merge")),true,"merge_dialog",true); + if (!dlg) { + return; + } + dlg->setHelp("merging-items","kdesvn"); + ptr->setDest(target); + ptr->setSrc1(src1); + ptr->setSrc2(src1); + if (dlg->exec()==QDialog::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 kdesvnfilelist::slotDropped(QDropEvent* event,QListViewItem*item) +{ + KURL::List urlList; + QMap<QString,QString> metaData; + QDropEvent::Action action = event->action(); + if (!event || m_pList->intern_dropRunning||!KURLDrag::decode( event, urlList, metaData)||urlList.count()<1) { + return; + } + kdDebug()<<"slotDropped"<<endl; + QString 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()*/) { + QString path = urlList[0].path(); + QFileInfo fi(path); + if (!isWorkingCopy()) { + slotImportIntoDir(urlList[0],tdir,fi.isDir()); + } else { + //m_pList->stopScan(); + KIO::Job * job = 0L; + job = KIO::copy(urlList,tdir); + connect( job, SIGNAL( result( KIO::Job * ) ),SLOT( slotCopyFinished( KIO::Job * ) ) ); + dispDummy(); + event->acceptAction(); + return; + } + } + } else { + kdDebug()<<"Dropped from inside " << action << endl; + int root_x, root_y, win_x, win_y; + uint keybstate; + QDropEvent::Action action = QDropEvent::UserAction; + KeyState::keystate(&root_x,&root_y,&win_x,&win_y,&keybstate); + if (keybstate&Qt::ControlButton) { + kdDebug()<<"Control pressed" << endl; + action = QDropEvent::Copy; + } else if (keybstate&Qt::ShiftButton) { + kdDebug()<<"Shift pressed" << endl; + action = QDropEvent::Move; + } + /* converting urls to interal style */ + QString nProto; + if (isWorkingCopy()) { + nProto=""; + } else { + nProto = svn::Url::transformProtokoll(urlList[0].protocol()); + } + KURL::List::Iterator it = urlList.begin(); + QStringList l; + for (;it!=urlList.end();++it) { + l = QStringList::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=QCursor::pos(); + QTimer::singleShot(0,this,SLOT(slotInternalDrop())); + +// internalDrop(action,urlList,tdir); + } +} + +void kdesvnfilelist::slotInternalDrop() +{ + QDropEvent::Action action = m_pList->intern_drop_action; + if (action==QDropEvent::UserAction) { + QPopupMenu popup; + popup.insertItem(SmallIconSet("goto"), i18n( "Move Here" ) + "\t" + KKey::modFlagLabel( KKey::SHIFT ), 2 ); + popup.insertItem(SmallIconSet("editcopy"), i18n( "Copy Here" ) + "\t" + KKey::modFlagLabel( KKey::CTRL ), 1 ); + popup.insertSeparator(); + popup.insertItem(SmallIconSet("cancel"), i18n( "Cancel" ) + "\t" + KKey( Qt::Key_Escape ).toString(), 5); + int result = popup.exec(m_pList->intern_drop_pos); + switch (result) { + case 1 : action = QDropEvent::Copy; break; + case 2 : action = QDropEvent::Move; break; + default: + { + m_pList->intern_dropRunning=false; + return; + } + } + } + if (action==QDropEvent::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 kdesvnfilelist::slotRename() + */ +void kdesvnfilelist::slotRename() +{ + copy_move(true); +} +void kdesvnfilelist::slotCopy() +{ + copy_move(false); +} + +void kdesvnfilelist::copy_move(bool move) +{ + if (isWorkingCopy()&&singleSelected()==firstChild()) { + return; + } + bool ok, force; + FileListViewItem*which = singleSelected(); + if (!which) return; + QString 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 kdesvnfilelist::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 kdesvnfilelist::slotCopyFinished( KIO::Job *) + */ +void kdesvnfilelist::slotCopyFinished( KIO::Job * job) +{ + if (m_pList->m_DirWatch) { + m_pList->m_DirWatch->startScan(false); + } + if (job) { + bool ok = true; + qApp->exit_loop(); + if (job->error()) { + job->showErrorDialog(this); + ok = false; + } + // always just connect a CopyJob here!!!! + if (ok) { + KURL::List lst = static_cast<KIO::CopyJob*>(job)->srcURLs(); + KURL turl = static_cast<KIO::CopyJob*>(job)->destURL(); + QString base = turl.path(1); + KURL::List::iterator iter; + QValueList<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 kdesvnfilelist::slotDelete() + */ +void kdesvnfilelist::slotDelete() +{ + m_deletePerfect = true; + QPtrList<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); + + QValueList<svn::Path> items; + QStringList displist; + KURL::List kioList; + while ((cur=liter.current())!=0){ + ++liter; + if (!cur->isRealVersioned()) { + KURL _uri; _uri.setPath(cur->fullName()); + kioList.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 (kioList.count()>0) { + KIO::Job*aJob = KIO::del(kioList); + connect(aJob,SIGNAL(result (KIO::Job *)),this,SLOT(slotDeleteFinished(KIO::Job*))); + dispDummy(); + } + if (m_deletePerfect && items.size()>0) { + m_SvnWrapper->makeDelete(items); + } + refreshCurrentTree(); + //m_pList->startScan(); +} + +/*! + \fn kdesvnfilelist::slotDeleteFinished(KIO::Job*) + */ +void kdesvnfilelist::slotDeleteFinished(KIO::Job*job) +{ + if (job) { + qApp->exit_loop(); + if (job->error()) { + job->showErrorDialog(this); + m_deletePerfect = false; + } + } +} + +/*! + \fn kdesvnfilelist::dispDummy() + */ +void kdesvnfilelist::dispDummy() +{ + // wait for job + QLabel dummy(this,0,WStyle_NoBorder|WShowModal); + QSize 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(); + qApp->enter_loop(); + dummy.hide(); +} + + +/*! + \fn kdesvnfilelist::slotLock() + */ +void kdesvnfilelist::slotLock() +{ + QPtrList<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,QString(i18n("Lock message")),true,"locking_log_msg"); + if (!dlg) return; + ptr->initHistory(); + ptr->hideDepth(true); + QCheckBox*_stealLock = new QCheckBox("",ptr,"create_dir_checkbox"); + _stealLock->setText(i18n("Steal lock?")); + ptr->addItemWidget(_stealLock); + ptr->m_keepLocksButton->hide(); + + if (dlg->exec()!=QDialog::Accepted) { + ptr->saveHistory(true); + delete dlg; + return; + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"locking_log_msg",false); + + QString logMessage = ptr->getMessage(); + bool steal = _stealLock->isChecked(); + ptr->saveHistory(false); + + QStringList displist; + while ((cur=liter.current())!=0){ + ++liter; + displist.append(cur->fullName()); + } + m_SvnWrapper->makeLock(displist,logMessage,steal); + refreshCurrentTree(); +} + + +/*! + \fn kdesvnfilelist::slotUnlock() + */ +void kdesvnfilelist::slotUnlock() +{ + QPtrList<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; + + QStringList displist; + while ((cur=liter.current())!=0){ + ++liter; + displist.append(cur->fullName()); + } + m_SvnWrapper->makeUnlock(displist,breakit); + refreshCurrentTree(); +} + + +/*! + \fn kdesvnfilelist::slotIgnore() + */ +void kdesvnfilelist::slotIgnore() +{ + SvnItem*item = singleSelected(); + if (!item || item->isRealVersioned()) return; + if (m_SvnWrapper->makeIgnoreEntry(item,item->isIgnored())) { + refreshCurrentTree(); + } +} + + +/*! + \fn kdesvnfilelist::slotBlame() + */ +void kdesvnfilelist::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 kdesvnfilelist::slotRangeBlame() + */ +void kdesvnfilelist::slotRangeBlame() +{ + SvnItem*k = singleSelected(); + if (!k) return; + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + if (dlg->exec()==QDialog::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 kdesvnfilelist::slotSimpleBaseDiff() +{ + FileListViewItem*kitem = singleSelected(); + if (isWorkingCopy()) + { + chdir(baseUri().local8Bit()); + } + + QString 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 kdesvnfilelist::slotSimpleHeadDiff() +{ + FileListViewItem*kitem = singleSelected(); + QString 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 kdesvnfilelist::slotDisplayLastDiff() +{ + FileListViewItem*kitem = singleSelected(); + QString what; + if (isWorkingCopy()) + { + chdir(baseUri().local8Bit()); + } + svn::Revision end = svn::Revision::PREV; + if (!kitem) { + if (isWorkingCopy()) { + QListViewItem*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 kdesvnfilelist::slotDiffPathes() +{ + QPtrList<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); + QString 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 kdesvnfilelist::slotMkdir() + */ +void kdesvnfilelist::slotMkdir() +{ + SvnItem*k = singleSelected(); + QString parentDir; + if (k) { + if (!k->isDir()) { + KMessageBox::sorry(0,i18n("May not make subdirs of a file")); + return; + } + parentDir=k->fullName(); + } else { + parentDir=baseUri(); + } + QString ex = m_SvnWrapper->makeMkdir(parentDir); + if (!ex.isEmpty()) { + slotDirAdded(ex,static_cast<FileListViewItem*>(k)); + } +} + +void kdesvnfilelist::slotMkBaseDirs() +{ + bool isopen = baseUri().length()>0; + if (!isopen) { + return; + } + QString parentDir=baseUri(); + QStringList targets; + targets.append(parentDir+"/trunk"); + targets.append(parentDir+"/branches"); + targets.append(parentDir+"/tags"); + QString msg = i18n("Automatic generated base layout by kdesvn"); + isopen = m_SvnWrapper->makeMkdir(targets,msg); + if (isopen) { + slotDirAdded(targets[0],0); +// slotDirAdded(targets[1],0); +// slotDirAdded(targets[2],0); + } +} + +/*! + \fn kdesvnfilelist::slotDiffRevisions() + */ +void kdesvnfilelist::slotDiffRevisions() +{ + SvnItem*k = singleSelected(); + QString what; + if (isWorkingCopy()) + { + chdir(baseUri().local8Bit()); + } + + if (!k) { + what=(isWorkingCopy()?".":baseUri()); + }else{ + what = relativePath(k); + } + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + if (dlg->exec()==QDialog::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 kdesvnfilelist::slotSelectBrowsingRevision() +{ + if (isWorkingCopy()) return; + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + rdlg->setStartOnly(true); + if (dlg->exec()==QDialog::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 kdesvnfilelist::slotRevisionCat() + */ +void kdesvnfilelist::slotRevisionCat() +{ + SvnItem*k = singleSelected(); + if (!k) return; + Rangeinput_impl*rdlg; + KDialogBase*dlg = createDialog(&rdlg,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + rdlg->setStartOnly(true); + if (dlg->exec()==QDialog::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 kdesvnfilelist::refreshItem(FileListViewItem*) + */ +bool kdesvnfilelist::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 kdesvnfilelist::slotCheckUpdates() + */ +void kdesvnfilelist::slotCheckUpdates() +{ + m_SvnWrapper->createUpdateCache(baseUri()); +} + +/*! + \fn kdesvnfilelist::reinitItems(FileListViewItem*_item = 0) + */ +void kdesvnfilelist::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 kdesvnfilelist::slotInfo() + */ +void kdesvnfilelist::slotInfo() +{ + QPtrList<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 kdesvnfilelist::slotDirItemCreated(const QString&) + */ +void kdesvnfilelist::slotDirItemCreated(const QString&what) +{ + m_pList->stopDirTimer(); + m_pList->dirItems[what]='C'; + kdDebug()<<"slotDirItemCreated "<<what<<endl; + m_pList->startDirTimer(); +} + + +void kdesvnfilelist::updateParents(FileListViewItem*item) +{ + if (!item || !item->parent()) return; + FileListViewItem*it = static_cast<FileListViewItem*>(item->parent()); + it->update(); + updateParents(it); +} + +/*! + \fn kdesvnfilelist::slotDirItemDirty(const QString&) + */ +void kdesvnfilelist::slotDirItemDirty(const QString&what) +{ + m_pList->stopDirTimer(); + m_pList->dirItems[what]='M'; + m_pList->startDirTimer(); +} + +void kdesvnfilelist::_propListTimeout() +{ + dispProperties(false); +} + +void kdesvnfilelist::slotDisplayProperties() +{ + dispProperties(true); +} + +void kdesvnfilelist::dispProperties(bool force) +{ + CursorStack a(Qt::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,QString("")); + 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 kdesvnfilelist::_dirwatchTimeout() +{ + kdDebug()<<"dirtimer"<<endl; + QMap<QString,QChar>::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) + { + QString what = it.key(); + QChar 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 { + QListViewItem *_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()) { + QFileInfo 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 kdesvnfilelist::slotDirItemDeleted(const QString&) + */ +void kdesvnfilelist::slotDirItemDeleted(const QString&what) +{ + m_pList->stopDirTimer(); + m_pList->m_fileTip->setItem(0); + QMap<QString,QChar>::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 kdesvnfilelist::gotPreview( const KFileItem*, const QPixmap&) +{ +#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 kdesvnfilelist::gotPreviewResult() +{ +// m_previewJob = 0; +} + +FileListViewItem* kdesvnfilelist::findEntryItem(const QString&what,FileListViewItem*startAt) +{ + if (!startAt && !what.startsWith(baseUri())) return 0; + QString _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 kdesvnfilelist::contentsMouseMoveEvent( QMouseEvent *e ) + */ +void kdesvnfilelist::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if (!m_pList->mousePressed) + { + if (Kdesvnsettings::display_file_tips()) { + + QPoint vp = contentsToViewport( e->pos() ); + FileListViewItem*item = isExecuteArea( vp ) ? static_cast<FileListViewItem*>(itemAt( vp )) : 0L; + + if (item) { + vp.setY( itemRect( item ).y() ); + QRect rect( viewportToContents( vp ), QSize(20, item->height()) ); + m_pList->m_fileTip->setItem( static_cast<SvnItem*>(item), rect, item->pixmap(0)); + m_pList->m_fileTip->setPreview(KGlobalSettings::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() > QApplication::startDragDistance()) + { + m_pList->m_fileTip->setItem(0); + m_pList->mousePressed=false; + //beginDrag(); + } + } + KListView::contentsMouseMoveEvent( e ); +} + +void kdesvnfilelist::contentsMousePressEvent(QMouseEvent*e) +{ + KListView::contentsMousePressEvent(e); + m_pList->m_fileTip->setItem(0); + QPoint p(contentsToViewport( e->pos())); + QListViewItem *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 kdesvnfilelist::contentsMouseReleaseEvent(QMouseEvent*e) +{ + KListView::contentsMouseReleaseEvent(e); + m_pList->mousePressed = false; +} + +/*! + \fn kdesvnfilelist::contentsWheelEvent( QWheelEvent * e ) + */ +void kdesvnfilelist::contentsWheelEvent( QWheelEvent * e ) +{ + // when scrolling with mousewheel, stop possible pending filetip + m_pList->m_fileTip->setItem(0); + KListView::contentsWheelEvent( e ); +} + +void kdesvnfilelist::leaveEvent(QEvent*e) +{ + m_pList->m_fileTip->setItem( 0 ); + KListView::leaveEvent( e ); +} + +void kdesvnfilelist::slotSettingsChanged() +{ + m_pList->m_fileTip->setOptions(!isNetworked()&&Kdesvnsettings::display_file_tips()&& + QToolTip::isGloballyEnabled(),true,6); + if (m_pList->reReadSettings()) { + refreshCurrentTree(); + } else { + viewport()->repaint(); + } + enableActions(); + sort(); + if (m_SvnWrapper && !m_SvnWrapper->doNetworking()) { + m_SvnWrapper->stopFillCache(); + } +} + + +/*! + \fn kdesvnfilelist::slotRelocate() + */ +void kdesvnfilelist::slotRelocate() +{ + if (!isWorkingCopy()) return; + SvnItem*k = SelectedOrMain(); + if (!k) { + KMessageBox::error(0,i18n("Error getting entry to relocate")); + return; + } + QString 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()==QDialog::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 kdesvnfilelist::checkUnversionedDirs( FileListViewItem * _parent ) +{ + QDir 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( QDir::Files | QDir::Dirs ); + + const QFileInfoList *list = d.entryInfoList(); + if (!list) { + return; + } + QFileInfoListIterator nonversioned_it( *list ); + QFileInfo *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 QDir 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 kdesvnfilelist::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 kdesvnfilelist::slotRescanIcons(bool checkNewer) +{ + rescanIconsRec(0L,checkNewer); +} + + +/*! + \fn kdesvnfilelist::slotCheckNewItems() + */ +void kdesvnfilelist::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 kdesvnfilelist::slotMakeRangeLog() + */ +void kdesvnfilelist::slotMakeRangeLog() +{ + QString 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,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + bool list = Kdesvnsettings::self()->log_always_list_changed_files(); + int i = dlg->exec(); + if (i==QDialog::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 kdesvnfilelist::slotMakeTree() +{ + QString 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 kdesvnfilelist::slotMakePartTree() +{ + QString 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,QString(i18n("Revisions")),true,"revisions_dlg"); + if (!dlg) { + return; + } + int i = dlg->exec(); + Rangeinput_impl::revision_range r; + if (i==QDialog::Accepted) { + r = rdlg->getRange(); + } + dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"revisions_dlg",false); + + if (i==QDialog::Accepted) { + svn::Revision rev(isWorkingCopy()?svn::Revision::UNDEFINED:m_pList->m_remoteRevision); + m_SvnWrapper->makeTree(what,rev,r.first,r.second); + } +} + +/*! + \fn kdesvnfilelist::slotMakeLog() + */ +void kdesvnfilelist::slotMakeLog() +{ + QString 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& kdesvnfilelist::remoteRevision()const +{ + return m_pList->m_remoteRevision; +} + + +/*! + \fn kdesvnfilelist::slotOpenWith() + */ +void kdesvnfilelist::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 kdesvnfilelist::slotUnfoldTree() +{ + StopSimpleDlg sdlg(0,0,i18n("Unfold tree"),i18n("Unfold all folder")); + + connect(this,SIGNAL(sigListError()), + &sdlg,SLOT(makeCancel())); + + QListViewItemIterator it(this); + QTime t;t.start(); + + setUpdatesEnabled(false); + { + WidgetBlockStack a(this); + while (QListViewItem* 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 kdesvnfilelist::slotFoldTree() +{ + QListViewItemIterator it(this); + while (QListViewItem* item = it.current()) + { + // don't close the top level directory + if (item->isExpandable() && item->parent()) + item->setOpen(false); + + ++it; + } +} + +/*! + \fn kdesvnfilelist::uniqueSelected() + */ +bool kdesvnfilelist::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 kdesvnfilelist::slotChangeProperties(const svn::PropertiesMap&pm,const QValueList<QString>&dellist,const QString&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 kdesvnfilelist::slotUpdateLogCache() +{ + if (baseUri().length()>0 && m_SvnWrapper->doNetworking()) { + KAction*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 "kdesvnfilelist.moc" |