KDevelop API Documentation

filegroupswidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2001-2002 by Bernd Gehrmann                             *
00003  *   bernd@kdevelop.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  ***************************************************************************/
00011 
00012 #include "filegroupswidget.h"
00013 
00014 #include <qfileinfo.h>
00015 #include <qdir.h>
00016 #include <qheader.h>
00017 #include <qtimer.h>
00018 #include <qvbox.h>
00019 #include <qregexp.h>
00020 
00021 #include <kdebug.h>
00022 #include <kdialogbase.h>
00023 #include <kiconloader.h>
00024 #include <klocale.h>
00025 #include <kpopupmenu.h>
00026 #include <kaction.h>
00027 #include <kdeversion.h>
00028 
00029 #include "kdevcore.h"
00030 #include "kdevproject.h"
00031 #include "kdevmainwindow.h"
00032 #include "kdevpartcontroller.h"
00033 #include "domutil.h"
00034 
00035 #include "filegroupspart.h"
00036 #include "filegroupsconfigwidget.h"
00037 
00038 
00039 // Translations for strings in the project file
00040 static const char *translations[] = {
00041     I18N_NOOP("Sources"),
00042     I18N_NOOP("Translations"),
00043     I18N_NOOP("User Interface"),
00044     I18N_NOOP("Others")
00045 };
00046 
00047 class FileComparator {
00048 public:
00049     virtual ~FileComparator(){
00050     };
00051     virtual bool matches(const QString& name) const = 0;
00052 };
00053 
00054 class RegExpComparator : public FileComparator {
00055 public:
00056     RegExpComparator(const QString& pattern) : m_exp(pattern, true, true){
00057     }
00058     bool matches(const QString& name) const{
00059         return m_exp.exactMatch(name);
00060     }
00061 private:
00062     const QRegExp m_exp;
00063 };
00064 
00065 class EndingComparator : public FileComparator {
00066 public:
00067     EndingComparator(const QString& pattern) : m_pattern ( pattern){
00068     }
00069     bool matches(const QString& name) const{
00070         return name.endsWith(m_pattern);
00071     }
00072 private:
00073     const QString m_pattern;
00074 };
00075 
00076 class FileViewFolderItem : public QListViewItem
00077 {
00078 public:
00079     FileViewFolderItem(QListView *parent, const QString &name, const QString &pattern);
00080     bool matches(const QString &fileName);
00081 
00082 private:
00083     QPtrList<FileComparator> m_patterns;
00084 };
00085 
00086 
00087 FileViewFolderItem::FileViewFolderItem(QListView *parent, const QString &name, const QString &pattern)
00088     : QListViewItem(parent, name)
00089 {
00090     setPixmap(0, SmallIcon("folder"));
00091     m_patterns.setAutoDelete(true);
00092     QStringList patternstring = QStringList::split(';', pattern);
00093     QStringList::ConstIterator theend = patternstring.end();
00094     for (QStringList::ConstIterator ci = patternstring.begin(); ci != theend; ++ci)
00095     {
00096         QString pattern = *ci;
00097         QString tail = pattern.right( pattern.length() - 1 );
00098 
00099         if ( (tail).contains('*') || pattern.contains('?') || pattern.contains('[') || pattern.contains(']') )
00100         {
00101             m_patterns.append( new RegExpComparator( pattern ) );
00102         }
00103         else
00104         {
00105             if ( pattern.startsWith("*") )
00106             {
00107                 m_patterns.append( new EndingComparator( tail ) );
00108             }
00109             else
00110             {
00111                 m_patterns.append( new EndingComparator( pattern ) );
00112             }
00113         }
00114     }
00115 }
00116 
00117 
00118 bool FileViewFolderItem::matches(const QString &fileName)
00119 {
00120     // Test with the file path, so that "*ClientServer/*.h" patterns work
00121     QString fName = QFileInfo(fileName).filePath();
00122 
00123     QPtrList<FileComparator>::ConstIterator theend = m_patterns.end();
00124     for (QPtrList<FileComparator>::ConstIterator ci = m_patterns.begin(); ci != theend; ++ci)
00125         if ((*ci)->matches(fName))
00126         return true;
00127 
00128     return false;
00129 }
00130 
00131 
00132 class FileGroupsFileItem : public QListViewItem
00133 {
00134 public:
00135     FileGroupsFileItem(QListViewItem *parent, const QString &fileName);
00136     QString fileName() const
00137     { return fullname; }
00138 
00139 private:
00140     QString fullname;
00141 };
00142 
00143 
00144 FileGroupsFileItem::FileGroupsFileItem(QListViewItem *parent, const QString &fileName)
00145     : QListViewItem(parent), fullname(fileName)
00146 {
00147     setPixmap(0, SmallIcon("document"));
00148     QFileInfo fi(fileName);
00149     setText(0, fi.fileName());
00150     setText(1, "./" + fi.dirPath());
00151 }
00152 
00153 FileGroupsWidget::FileGroupsWidget(FileGroupsPart *part)
00154     : KListView(0, "file view widget"),
00155     m_actionToggleShowNonProjectFiles( 0 ), m_actionToggleDisplayLocation( 0 )
00156 {
00157     /*
00158     Setting Location ID to -1 so I can check if it has been loaded later.
00159     If I dont, it will remove the name column and this is not too good :-)
00160     Is there any better way to do this?
00161     */
00162     LocationID=-1;
00163 
00164     setFocusPolicy(ClickFocus);
00165     setRootIsDecorated(true);
00166     setResizeMode(QListView::LastColumn);
00167     setSorting(-1);
00168     addColumn(i18n("Name"));
00169 //    addColumn(i18n("Location"));
00170 
00171     connect( this, SIGNAL(executed(QListViewItem*)),
00172              this, SLOT(slotItemExecuted(QListViewItem*)) );
00173     connect( this, SIGNAL(returnPressed(QListViewItem*)),
00174              this, SLOT(slotItemExecuted(QListViewItem*)) );
00175     connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
00176              this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) );
00177 
00178     m_actionToggleShowNonProjectFiles = new KToggleAction( i18n("Show Non Project Files"), KShortcut(),
00179     this, SLOT(slotToggleShowNonProjectFiles()), this, "actiontoggleshowshownonprojectfiles" );
00180 #if KDE_IS_VERSION(3,2,90)
00181     m_actionToggleShowNonProjectFiles->setCheckedState(i18n("Hide Non Project Files"));
00182 #endif
00183     m_actionToggleShowNonProjectFiles->setWhatsThis(i18n("<b>Show non project files</b><p>Shows files that do not belong to a project in a file tree."));
00184 
00185     m_actionToggleDisplayLocation = new KToggleAction( i18n("Display Location Column"), KShortcut(),
00186         this, SLOT(slotToggleDisplayLocation()), this, "actiontoggleshowlocation" );
00187     m_actionToggleDisplayLocation->setWhatsThis(i18n("<b>Display the Location Column</b><p>Displays a column with the location of the files."));
00188 
00189     m_part = part;
00190     (void) translations; // supress compiler warning
00191 
00192     QDomDocument &dom = *m_part->projectDom();
00193     m_actionToggleShowNonProjectFiles->setChecked( !DomUtil::readBoolEntry(dom, "/kdevfileview/groups/hidenonprojectfiles") );
00194     m_actionToggleDisplayLocation->setChecked( !DomUtil::readBoolEntry(dom, "/kdevfileview/groups/hidenonlocation") );
00195 }
00196 
00197 
00198 FileGroupsWidget::~FileGroupsWidget()
00199 {
00200     QDomDocument &dom = *m_part->projectDom();
00201     DomUtil::writeBoolEntry( dom, "/kdevfileview/groups/hidenonprojectfiles", !m_actionToggleShowNonProjectFiles->isChecked() );
00202     DomUtil::writeBoolEntry( dom, "/kdevfileview/groups/hidenonlocation", !m_actionToggleDisplayLocation->isChecked() );
00203 }
00204 
00205 
00206 void FileGroupsWidget::slotItemExecuted(QListViewItem *item)
00207 {
00208     if (!item)
00209         return;
00210 
00211     // toggle open state for parents
00212     if (item->childCount() > 0)
00213         setOpen(item, !isOpen(item));
00214 
00215     // Is it a group item?
00216     if (!item->parent())
00217         return;
00218 
00219     FileGroupsFileItem *fgfitem = static_cast<FileGroupsFileItem*>(item);
00220     m_part->partController()->editDocument(KURL::fromPathOrURL( m_part->project()->projectDirectory() + "/" + fgfitem->fileName() ));
00221 }
00222 
00223 
00224 void FileGroupsWidget::slotContextMenu(KListView *, QListViewItem *item, const QPoint &p)
00225 {
00226     KPopupMenu popup(i18n("File Groups"), this);
00228     int customizeId = popup.insertItem(i18n("Customize..."));
00229     popup.setWhatsThis(customizeId, i18n("<b>Customize</b><p>Opens <b>Customize File Groups</b> dialog where the groups can be managed."));
00230     if (item) {
00231     if (item->parent()) {
00232         // Not for group items
00233         FileGroupsFileItem *fvfitem = static_cast<FileGroupsFileItem*>(item);
00234         QString pathName = m_part->project()->projectDirectory() + QDir::separator() + fvfitem->fileName();
00235         FileContext context( pathName, false);
00236         m_part->core()->fillContextMenu(&popup, &context);
00237     }
00238     else{
00239         QStringList file_list;
00240         QListViewItem* i = item->firstChild();
00241         while(i){
00242             FileGroupsFileItem *fvgitem = static_cast<FileGroupsFileItem*>(i);
00243             file_list << fvgitem->fileName();
00244             i = i->nextSibling();
00245         }
00246         FileContext context(file_list);
00247         m_part->core()->fillContextMenu(&popup, &context);
00248     }
00249     }
00250     m_actionToggleShowNonProjectFiles->plug( &popup );
00251     m_actionToggleDisplayLocation->plug( &popup );
00252 
00253     int res = popup.exec(p);
00254     if (res == customizeId) {
00255         KDialogBase dlg(KDialogBase::TreeList, i18n("Customize File Groups"),
00256                         KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, this,
00257                         "customization dialog");
00258         QVBox *vbox = dlg.addVBoxPage(i18n("File Groups"));
00259         FileGroupsConfigWidget *w = new FileGroupsConfigWidget(m_part, vbox, "file groups config widget");
00260         connect(&dlg, SIGNAL(okClicked()), w, SLOT(accept()));
00261         dlg.exec();
00262     }
00263 }
00264 
00265 QStringList FileGroupsWidget::allFilesRecursively( QString const & dir )
00266 {
00267     QStringList filelist;
00268     QString reldir = dir.mid( m_part->project()->projectDirectory().length() +1 );
00269 
00270     // recursively fetch all files in subdirectories
00271     QStringList subdirs = QDir( dir ).entryList( QDir::Dirs );
00272     QValueListIterator<QString> it = subdirs.begin();
00273     while ( it != subdirs.end() )
00274     {
00275         if ( *it != "." && *it != ".." )
00276         {
00277             filelist += allFilesRecursively( dir + "/"+ *it );
00278         }
00279         ++it;
00280     }
00281 
00282     // append the project relative directory path to all files in the current directory
00283     QStringList dirlist = QDir( dir ).entryList( QDir::Files );
00284     QValueListIterator<QString> itt = dirlist.begin();
00285     while ( itt != dirlist.end() )
00286     {
00287         if ( reldir.isEmpty() )
00288         {
00289             filelist << *itt;
00290         }
00291         else
00292         {
00293             filelist << reldir + "/" + *itt;
00294         }
00295         ++itt;
00296     }
00297 
00298     return filelist;
00299 }
00300 
00301 void FileGroupsWidget::refresh()
00302 {
00303     while (firstChild())
00304         delete firstChild();
00305 
00306     if (m_actionToggleDisplayLocation->isChecked()) {
00307         // Display the Location column
00308     LocationID=addColumn(i18n("Location"));
00309     }
00310     else {
00311         // Remove the Location column
00312     //Need to check if the ID exists, if not do nothing!!
00313     if (LocationID!=-1)
00314         removeColumn(LocationID);
00315     }
00316     QDomDocument &dom = *m_part->projectDom();
00317     DomUtil::PairList list =
00318         DomUtil::readPairListEntry(dom, "/kdevfileview/groups", "group", "name", "pattern");
00319 
00320     FileViewFolderItem *lastGroup = 0;
00321 
00322     DomUtil::PairList::ConstIterator git;
00323     for (git = list.begin(); git != list.end(); ++git) {
00324         FileViewFolderItem *newItem = new FileViewFolderItem(this, (*git).first, (*git).second);
00325         if (lastGroup)
00326             newItem->moveItem(lastGroup);
00327         lastGroup = newItem;
00328     }
00329 
00330     QStringList allFiles;
00331     if (m_actionToggleShowNonProjectFiles->isChecked()) {
00332         // get all files in the project directory
00333         allFiles = allFilesRecursively( m_part->project()->projectDirectory() );
00334     }
00335     else {
00336         // get all project files
00337         allFiles = m_part->project()->allFiles();
00338     }
00339     QStringList::ConstIterator fit;
00340     for (fit = allFiles.begin(); fit != allFiles.end(); ++fit) {
00341         QListViewItem *item = firstChild();
00342         while (item) {
00343             FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item);
00344             if (fvgitem->matches(*fit)) {
00345                 (void) new FileGroupsFileItem(fvgitem, *fit);
00346                 break;
00347             }
00348             item = item->nextSibling();
00349         }
00350     }
00351 
00352     QListViewItem *item = firstChild();
00353     while (item) {
00354         item->sortChildItems(0, true);
00355         item = item->nextSibling();
00356     }
00357 }
00358 
00359 
00360 void FileGroupsWidget::addFile(const QString &fileName)
00361 {
00362     kdDebug(9017) << "FileView add " << fileName << endl;
00363 
00364     QListViewItem *item = firstChild();
00365     while (item) {
00366         FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item);
00367         if (fvgitem->matches(fileName))
00368         {
00369             QString f = fileName;
00370             if (fileName.contains(m_part->project()->projectDirectory()))
00371                 f = fileName.mid(m_part->project()->projectDirectory().length()+1);
00372             (void) new FileGroupsFileItem(fvgitem, f);
00373             fvgitem->sortChildItems(0, true);
00374             break;
00375         }
00376         item = item->nextSibling();
00377     }
00378 }
00379 
00380 void FileGroupsWidget::addFiles ( const QStringList& fileList )
00381 {
00382     QStringList::ConstIterator it;
00383 
00384     for ( it = fileList.begin(); it != fileList.end(); ++it )
00385     {
00386         this->addFile ( *it );
00387     }
00388 }
00389 
00390 void FileGroupsWidget::removeFile(const QString &fileName)
00391 {
00392     kdDebug(9017) << "FileView remove " << fileName << endl;
00393 
00394     QListViewItem *item = firstChild();
00395     while (item)
00396     {
00397         FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item);
00398         QListViewItem *childItem = fvgitem->firstChild();
00399         while (childItem)
00400         {
00401             FileGroupsFileItem *fgfitem = static_cast<FileGroupsFileItem*>(childItem);
00402             kdDebug ( 9017 ) << "fvfitem->fileName() is " << fgfitem->fileName() << endl;
00403             if (fgfitem->fileName() == fileName )
00404             {
00405                 kdDebug ( 9017 ) << "Deleting: " << fgfitem->fileName() << endl;
00406 
00407                 delete fgfitem;
00408                 return;
00409             }
00410             childItem = childItem->nextSibling();
00411         }
00412         item = item->nextSibling();
00413     }
00414 }
00415 
00416 void FileGroupsWidget::removeFiles ( const QStringList& fileList )
00417 {
00418     QStringList::ConstIterator it;
00419 
00420     for ( it = fileList.begin(); it != fileList.end(); ++it )
00421     {
00422         removeFile ( *it );
00423     }
00424 }
00425 
00426 void FileGroupsWidget::slotToggleShowNonProjectFiles()
00427 {
00428     refresh();
00429 }
00430 
00431 void FileGroupsWidget::slotToggleDisplayLocation()
00432 {
00433     refresh();
00434 }
00435 
00436 
00437 #include "filegroupswidget.moc"
00438 
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 00:03:57 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003