00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include <qpainter.h>
00013
#include <qheader.h>
00014
#include <qpopupmenu.h>
00015
#include <kaction.h>
00016
#include <klocale.h>
00017
#include <kdebug.h>
00018
00019
#include <kdevvcsfileinfoprovider.h>
00020
00021
#include <urlutil.h>
00022
#include <domutil.h>
00023
00024
#include "fileviewpart.h"
00025
#include "filetreewidget.h"
00026
#include "fileitemfactory.h"
00027
#include "vcsfiletreewidgetimpl.h"
00028
#include "vcscolorsconfigwidget.h"
00029
00030
using namespace filetreeview;
00031
00033
00035
00036 #define FILENAME_COLUMN 0
00037 #define STATUS_COLUMN 1
00038 #define WORKREVISION_COLUMN 2
00039 #define REPOREVISION_COLUMN 3
00040
00041 class VCSFileTreeViewItem :
public filetreeview::
FileTreeViewItem
00042 {
00043
public:
00044 VCSFileTreeViewItem(
KFileTreeViewItem* parent,
KFileItem* item,
KFileTreeBranch* branch,
bool pf )
00045 :
FileTreeViewItem( parent, item, branch, pf ),
m_statusColor( &
FileViewPart::vcsColors.unknown ) {}
00046 VCSFileTreeViewItem(
KFileTreeView* parent,
KFileItem* item,
KFileTreeBranch* branch )
00047 :
FileTreeViewItem( parent, item, branch ),
m_statusColor( &
FileViewPart::vcsColors.unknown ) {}
00048 virtual void paintCell(
QPainter *p,
const QColorGroup &cg,
int column,
int width,
int alignment )
00049 {
00050
00051
QColorGroup mycg( cg );
00052 mycg.setColor( QColorGroup::Base, *
m_statusColor );
00053 FileTreeViewItem::paintCell( p, mycg, column, width, alignment );
00054 }
00055
void setVCSInfo(
const VCSFileInfo &info );
00056
00057 QString fileName()
const {
return text(
FILENAME_COLUMN ); }
00058 QString workingRev()
const {
return text(
WORKREVISION_COLUMN ); }
00059 QString repositoryRev()
const {
return text(
REPOREVISION_COLUMN ); }
00060 QString status()
const {
return text(
STATUS_COLUMN ); }
00061 void setFileName(
const QString &p ) { setText(
FILENAME_COLUMN, p ); }
00062 void setWorkingRev(
const QString &p ) { setText(
WORKREVISION_COLUMN, p ); }
00063 void setRepositoryRev(
const QString &p ) { setText(
REPOREVISION_COLUMN, p ); }
00064
void setStatus(
const VCSFileInfo::FileState status );
00065
00066
private:
00067 QColor *
m_statusColor;
00068 };
00069
00071
00072 void VCSFileTreeViewItem::setVCSInfo(
const VCSFileInfo &info )
00073 {
00074
00075
setRepositoryRev( info.
repoRevision );
00076
setWorkingRev( info.
workRevision );
00077
setStatus( info.
state );
00078 }
00079
00081
00082 void VCSFileTreeViewItem::setStatus(
const VCSFileInfo::FileState status )
00083 {
00084 setText(
STATUS_COLUMN, VCSFileInfo::state2String( status ) );
00085
00086
switch (status)
00087 {
00088
case VCSFileInfo::Added:
00089
m_statusColor = &FileViewPart::vcsColors.
added;
00090
break;
00091
case VCSFileInfo::Uptodate:
00092
m_statusColor = &FileViewPart::vcsColors.
updated;
00093
break;
00094
case VCSFileInfo::Modified:
00095
m_statusColor = &FileViewPart::vcsColors.
modified;
00096
break;
00097
case VCSFileInfo::Conflict:
00098
m_statusColor = &FileViewPart::vcsColors.
conflict;
00099
break;
00100
case VCSFileInfo::Sticky:
00101
m_statusColor = &FileViewPart::vcsColors.
sticky;
00102
break;
00103
case VCSFileInfo::NeedsCheckout:
00104
m_statusColor = &FileViewPart::vcsColors.
needsCheckout;
00105
break;
00106
case VCSFileInfo::NeedsPatch:
00107
m_statusColor = &FileViewPart::vcsColors.
needsPatch;
00108
break;
00109
case VCSFileInfo::Unknown:
00110
m_statusColor = &FileViewPart::vcsColors.
unknown;
00111
break;
00112
case VCSFileInfo::Directory:
00113
default:
00114
00115
m_statusColor = &FileViewPart::vcsColors.
defaultColor;
00116
00117
break;
00118 }
00119 }
00120
00122
00124
00125 class VCSFileTreeBranchItem :
public filetreeview::
FileTreeBranchItem
00126 {
00127
public:
00128 VCSFileTreeBranchItem(
KFileTreeView* view,
const KURL& url,
const QString& name,
const QPixmap& pix,
00129
KDevVCSFileInfoProvider *vcsInfoProvider )
00130 :
FileTreeBranchItem( view, url, name, pix ),
m_vcsInfoProvider( vcsInfoProvider ) {}
00131
00132
virtual KFileTreeViewItem* createTreeViewItem(
KFileTreeViewItem* parent,
KFileItem* fileItem );
00133
00134
private:
00135 KDevVCSFileInfoProvider *
m_vcsInfoProvider;
00136 };
00137
00139
00140 KFileTreeViewItem*
VCSFileTreeBranchItem::createTreeViewItem(
KFileTreeViewItem* parent,
KFileItem* fileItem )
00141 {
00142
00143
if (!parent || !fileItem)
00144
return 0;
00145
00146
FileTreeWidget *lv = static_cast<filetreeview::FileTreeViewItem*>( parent )->listView();
00147
const KURL fileURL = fileItem->
url();
00148
bool isDirectory = lv->
projectFiles().contains( fileURL.
path() ) > 0;
00149
00150
VCSFileTreeViewItem *newItem =
new VCSFileTreeViewItem( parent, fileItem,
this, isDirectory );
00151
00152
QString fileName = fileURL.
fileName();
00153
QString dirName =
URLUtil::extractPathNameRelative( lv->
projectDirectory(), fileURL.
directory() );
00154
00155
const VCSFileInfoMap &vcsFiles = *
m_vcsInfoProvider->
status( dirName );
00156
00157
if (vcsFiles.contains( fileName ))
00158 newItem->
setVCSInfo( vcsFiles[ fileName ] );
00159
00160
00161
return newItem;
00162 }
00163
00165
00167
00168 class VCSBranchItemFactory :
public filetreeview::
BranchItemFactory
00169 {
00170
public:
00171 VCSBranchItemFactory(
KDevVCSFileInfoProvider *vcsInfoProvider ) :
m_vcsInfoProvider( vcsInfoProvider ) {}
00172 virtual filetreeview::FileTreeBranchItem *
makeBranchItem(
KFileTreeView* view,
const KURL& url,
const QString& name,
const QPixmap& pix )
00173 {
00174
return new VCSFileTreeBranchItem( view, url, name, pix,
m_vcsInfoProvider );
00175 }
00176
private:
00177 KDevVCSFileInfoProvider *
m_vcsInfoProvider;
00178 };
00179
00181
00183
00184 VCSFileTreeWidgetImpl::VCSFileTreeWidgetImpl(
FileTreeWidget *parent,
KDevVCSFileInfoProvider *infoProvider )
00185 :
FileTreeViewWidgetImpl( parent, "vcsfiletreewidgetimpl" ),
00186 m_actionToggleShowVCSFields( 0 ), m_actionSyncWithRepository( 0 ), m_vcsInfoProvider( infoProvider ),
00187 m_isSyncingWithRepository( false ), m_vcsStatusRequestedItem( 0 )
00188 {
00189
kdDebug(9017) <<
"VCSFileTreeWidgetImpl::VCSFileTreeWidgetImpl()" <<
endl;
00190
00191 Q_ASSERT(
m_vcsInfoProvider );
00192 setBranchItemFactory(
new VCSBranchItemFactory(
m_vcsInfoProvider ) );
00193
00194
00195 parent->
addColumn(
"Filename" );
00196 parent->
addColumn(
"Status" );
00197 parent->
addColumn(
"Work" );
00198 parent->
addColumn(
"Repo" );
00199
00200 connect( m_vcsInfoProvider, SIGNAL(statusReady(
const VCSFileInfoMap&,
void *)),
00201
this, SLOT(
vcsDirStatusReady(
const VCSFileInfoMap&,
void*)) );
00202
00203 connect( m_vcsInfoProvider, SIGNAL(destroyed()), SIGNAL(
implementationInvalidated()) );
00204
00205
m_actionToggleShowVCSFields =
new KToggleAction( i18n(
"Show VCS Fields"),
KShortcut(),
00206
this,
"actiontoggleshowvcsfieldstoggleaction" );
00207
QString aboutAction = i18n(
"<b>Show VCS fields</b><p>Shows <b>Revision</b> and <b>Timestamp</b> for each file contained in VCS repository.");
00208
m_actionToggleShowVCSFields->
setWhatsThis( aboutAction );
00209 connect(
m_actionToggleShowVCSFields, SIGNAL(toggled(
bool)),
this, SLOT(
slotToggleShowVCSFields(
bool)) );
00210
00211
m_actionSyncWithRepository =
new KAction( i18n(
"Sync with Repository"),
KShortcut(),
00212
this, SLOT(
slotSyncWithRepository()),
this,
"actionsyncwithrepository" );
00213 aboutAction = i18n(
"<b>Sync with repository</b><p>Synchronize file status with remote repository.");
00214
m_actionSyncWithRepository->
setWhatsThis( aboutAction );
00215
00216
QDomDocument &dom =
projectDom();
00217
m_actionToggleShowVCSFields->
setChecked( DomUtil::readBoolEntry(dom,
"/kdevfileview/tree/showvcsfields") );
00218
slotToggleShowVCSFields(
showVCSFields() );
00219 }
00220
00222
00223 VCSFileTreeWidgetImpl::~VCSFileTreeWidgetImpl()
00224 {
00225
kdDebug(9017) <<
"VCSFileTreeWidgetImpl::~VCSFileTreeWidgetImpl()" <<
endl;
00226
00227
QDomDocument &dom =
projectDom();
00228 DomUtil::writeBoolEntry( dom,
"/kdevfileview/tree/showvcsfields",
showVCSFields() );
00229 }
00230
00232
00233 bool VCSFileTreeWidgetImpl::canReloadTree()
const
00234
{
00235
return !
m_isSyncingWithRepository;
00236 }
00237
00239
00240 void VCSFileTreeWidgetImpl::fillPopupMenu(
QPopupMenu *popupMenu,
QListViewItem *item )
const
00241
{
00242 FileTreeViewWidgetImpl::fillPopupMenu( popupMenu, item );
00243
00244
00245
m_actionToggleShowVCSFields->
plug( popupMenu );
00246
00247
00248
FileTreeViewItem *fileItem = static_cast<FileTreeViewItem *>( item );
00249
if (fileItem->
isDir())
00250 {
00251
m_vcsStatusRequestedItem = fileItem;
00252 popupMenu->insertSeparator();
00253
m_actionSyncWithRepository->
plug( popupMenu );
00254 }
00255 }
00256
00258
00259 void VCSFileTreeWidgetImpl::slotToggleShowVCSFields(
bool checked )
00260 {
00261
kdDebug(9017) <<
"VCSFileTreeWidgetImpl::slotToggleShowVCSFields()" <<
endl;
00262
00263
if (checked)
00264 {
00265 setColumnWidth( 0,
contentsWidth() / 2 );
00266 setColumnWidth( 1,
contentsWidth() / 4 );
00267 setColumnWidth( 2,
contentsWidth() / 5 );
00268 setColumnWidth( 3,
contentsWidth() / 5 );
00269
header()->show();
00270 }
00271
else
00272 {
00273 setColumnWidth( 3 ,0 );
00274 setColumnWidth( 2 ,0 );
00275 setColumnWidth( 1, 0 );
00276 setColumnWidth( 0,
contentsWidth() );
00277
header()->hide();
00278 }
00279
00280
triggerUpdate();
00281 }
00282
00284
00285 bool VCSFileTreeWidgetImpl::showVCSFields()
const
00286
{
00287
return m_actionToggleShowVCSFields->
isChecked();
00288 }
00289
00291
00292 void VCSFileTreeWidgetImpl::vcsDirStatusReady(
const VCSFileInfoMap &modifiedFiles,
void *callerData )
00293 {
00294
kdDebug(9017) <<
"VCSFileTreeWidgetImpl::vcsDirStatusReady(const VCSFileInfoMap &, void*)" <<
endl;
00295
00296
VCSFileTreeViewItem *item = static_cast<VCSFileTreeViewItem*>( callerData );
00297 Q_ASSERT( item );
00298
00299 item = static_cast<VCSFileTreeViewItem*>( item->firstChild() );
00300
while (item)
00301 {
00302
const QString fileName = item->
fileName();
00303
kdDebug(9017) <<
"Widget item filename is: " << fileName <<
endl;
00304
if (modifiedFiles.contains( fileName ))
00305 {
00306
const VCSFileInfo &vcsInfo = modifiedFiles[ fileName ];
00307
kdDebug(9017) <<
"Nice! Found info for this file: " << vcsInfo.
toString() <<
endl;
00308 item->
setVCSInfo( modifiedFiles[ fileName ] );
00309 }
00310
else
00311
kdDebug(9017) <<
"Map does not contain anything useful about this file ;-( " << fileName <<
endl;
00312 item = static_cast<VCSFileTreeViewItem*>( item->nextSibling() );
00313 }
00314
triggerUpdate();
00315
00316
m_isSyncingWithRepository =
false;
00317 }
00318
00320
00321 void VCSFileTreeWidgetImpl::slotSyncWithRepository()
00322 {
00323
kdDebug(9017) <<
"VCSFileTreeWidgetImpl::slotSyncWithRepository()" <<
endl;
00324
const VCSFileTreeViewItem *myFileItem = static_cast<VCSFileTreeViewItem *>(
m_vcsStatusRequestedItem );
00325
const QString relDirPath =
URLUtil::extractPathNameRelative(
projectDirectory(), myFileItem->
fileItem()->
url().
path() );
00326
kdDebug(9017) <<
"VCS Info requested for: " << relDirPath <<
endl;
00327
m_vcsInfoProvider->
requestStatus( relDirPath,
m_vcsStatusRequestedItem );
00328
m_isSyncingWithRepository =
true;
00329 }
00330
00331
#include "vcsfiletreewidgetimpl.moc"