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