00001
00002
00003
00004
00005
00006
00007
00008
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
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
00121
QString fName =
QFileInfo(fileName).filePath();
00122
00123
#if QT_VERSION < 0x030200
00124
QPtrListIterator<FileComparator> it(
m_patterns );
00125
while ( it.current() )
00126 {
00127
if ( (*it)->matches( fName ) )
00128 {
00129
return true;
00130 }
00131 ++it;
00132 }
00133
#else
00134
QPtrList<FileComparator>::ConstIterator theend =
m_patterns.end();
00135
for (
QPtrList<FileComparator>::ConstIterator ci =
m_patterns.begin(); ci != theend; ++ci)
00136
if ((*ci)->matches(fName))
00137
return true;
00138
#endif
00139
return false;
00140 }
00141
00142
00143 class FileGroupsFileItem :
public QListViewItem
00144 {
00145
public:
00146
FileGroupsFileItem(
QListViewItem *parent,
const QString &
fileName);
00147 QString fileName()
const
00148
{
return fullname; }
00149
00150
private:
00151 QString fullname;
00152 };
00153
00154
00155 FileGroupsFileItem::FileGroupsFileItem(
QListViewItem *parent,
const QString &fileName)
00156 :
QListViewItem(parent), fullname(fileName)
00157 {
00158 setPixmap(0, SmallIcon(
"document"));
00159
QFileInfo fi(fileName);
00160 setText(0, fi.fileName());
00161 setText(1,
"./" + fi.dirPath());
00162 }
00163
00164 FileGroupsWidget::FileGroupsWidget(
FileGroupsPart *part)
00165 :
KListView(0, "
file view widget"),
00166 m_actionToggleShowNonProjectFiles( 0 ), m_actionToggleDisplayLocation( 0 )
00167 {
00168
00169
00170
00171
00172
00173
LocationID=-1;
00174
00175 setFocusPolicy(ClickFocus);
00176 setRootIsDecorated(
true);
00177 setResizeMode(QListView::LastColumn);
00178 setSorting(-1);
00179 addColumn(i18n(
"Name"));
00180
00181
00182 connect(
this, SIGNAL(executed(
QListViewItem*)),
00183
this, SLOT(
slotItemExecuted(
QListViewItem*)) );
00184 connect(
this, SIGNAL(returnPressed(
QListViewItem*)),
00185
this, SLOT(
slotItemExecuted(
QListViewItem*)) );
00186 connect(
this, SIGNAL(contextMenu(
KListView*,
QListViewItem*,
const QPoint&)),
00187
this, SLOT(
slotContextMenu(
KListView*,
QListViewItem*,
const QPoint&)) );
00188
00189
m_actionToggleShowNonProjectFiles =
new KToggleAction( i18n(
"Show Non Project Files"),
KShortcut(),
00190
this, SLOT(
slotToggleShowNonProjectFiles()),
this,
"actiontoggleshowshownonprojectfiles" );
00191
m_actionToggleShowNonProjectFiles->
setWhatsThis(i18n(
"<b>Show non project files</b><p>Shows files that do not belong to a project in a file tree."));
00192
00193
m_actionToggleDisplayLocation =
new KToggleAction( i18n(
"Display Location Column"),
KShortcut(),
00194
this, SLOT(
slotToggleDisplayLocation()),
this,
"actiontoggleshowlocation" );
00195
m_actionToggleDisplayLocation->
setWhatsThis(i18n(
"<b>Display the Location Column</b><p>Displays a columne with the location of the files."));
00196
00197
m_part = part;
00198 (
void)
translations;
00199
00200
QDomDocument &dom = *
m_part->
projectDom();
00201
m_actionToggleShowNonProjectFiles->
setChecked( !DomUtil::readBoolEntry(dom,
"/kdevfileview/groups/hidenonprojectfiles") );
00202
m_actionToggleDisplayLocation->
setChecked( !DomUtil::readBoolEntry(dom,
"/kdevfileview/groups/hidenonlocation") );
00203 }
00204
00205
00206 FileGroupsWidget::~FileGroupsWidget()
00207 {
00208
QDomDocument &dom = *
m_part->
projectDom();
00209 DomUtil::writeBoolEntry( dom,
"/kdevfileview/groups/hidenonprojectfiles", !
m_actionToggleShowNonProjectFiles->
isChecked() );
00210 DomUtil::writeBoolEntry( dom,
"/kdevfileview/groups/hidenonlocation", !
m_actionToggleDisplayLocation->
isChecked() );
00211 }
00212
00213
00214 void FileGroupsWidget::slotItemExecuted(
QListViewItem *item)
00215 {
00216
if (!item)
00217
return;
00218
00219
00220
if (item->childCount() > 0)
00221 setOpen(item, !isOpen(item));
00222
00223
00224
if (!item->parent())
00225
return;
00226
00227
FileGroupsFileItem *fgfitem = static_cast<FileGroupsFileItem*>(item);
00228
#if defined(KDE_MAKE_VERSION)
00229
m_part->
partController()->
editDocument(KURL::fromPathOrURL(
m_part->
project()->
projectDirectory() +
"/" + fgfitem->
fileName() ));
00230
#else
00231
m_part->
partController()->
editDocument(
QString(
"file://") +
m_part->
project()->
projectDirectory() +
"/" + fgfitem->
fileName() );
00232
#endif
00233
m_part->
mainWindow()->
lowerView(
this);
00234 }
00235
00236
00237 void FileGroupsWidget::slotContextMenu(
KListView *,
QListViewItem *item,
const QPoint &p)
00238 {
00239
KPopupMenu popup(i18n(
"File Groups"),
this);
00241
int customizeId = popup.insertItem(i18n(
"Customize..."));
00242 popup.setWhatsThis(customizeId, i18n(
"<b>Customize</b><p>Opens <b>Customize File Groups</b> dialog where the groups can be managed."));
00243
if (item) {
00244
if (item->parent()) {
00245
00246
FileGroupsFileItem *fvfitem = static_cast<FileGroupsFileItem*>(item);
00247
QString pathName =
m_part->
project()->
projectDirectory() + QDir::separator() + fvfitem->
fileName();
00248
FileContext context( pathName,
false);
00249
m_part->
core()->
fillContextMenu(&popup, &context);
00250 }
00251
else{
00252
QStringList file_list;
00253
QListViewItem* i = item->firstChild();
00254
while(i){
00255
FileGroupsFileItem *fvgitem = static_cast<FileGroupsFileItem*>(i);
00256 file_list << fvgitem->
fileName();
00257 i = i->nextSibling();
00258 }
00259
FileContext context(file_list);
00260
m_part->
core()->
fillContextMenu(&popup, &context);
00261 }
00262 }
00263
m_actionToggleShowNonProjectFiles->
plug( &popup );
00264
m_actionToggleDisplayLocation->
plug( &popup );
00265
00266
int res = popup.exec(p);
00267
if (res == customizeId) {
00268
KDialogBase dlg(KDialogBase::TreeList, i18n(
"Customize File Groups"),
00269 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok,
this,
00270
"customization dialog");
00271
QVBox *vbox = dlg.
addVBoxPage(i18n(
"File Groups"));
00272
FileGroupsConfigWidget *w =
new FileGroupsConfigWidget(
m_part, vbox,
"file groups config widget");
00273 connect(&dlg, SIGNAL(okClicked()), w, SLOT(accept()));
00274 dlg.exec();
00275 }
00276 }
00277
00278 QStringList FileGroupsWidget::allFilesRecursively(
QString const & dir )
00279 {
00280
QStringList filelist;
00281
QString reldir = dir.mid(
m_part->
project()->
projectDirectory().length() +1 );
00282
00283
00284
QStringList subdirs =
QDir( dir ).entryList( QDir::Dirs );
00285
QValueListIterator<QString> it = subdirs.begin();
00286
while ( it != subdirs.end() )
00287 {
00288
if ( *it !=
"." && *it !=
".." )
00289 {
00290 filelist +=
allFilesRecursively( dir +
"/"+ *it );
00291 }
00292 ++it;
00293 }
00294
00295
00296
QStringList dirlist = QDir( dir ).entryList( QDir::Files );
00297
QValueListIterator<QString> itt = dirlist.begin();
00298
while ( itt != dirlist.end() )
00299 {
00300
if ( reldir.isEmpty() )
00301 {
00302 filelist << *itt;
00303 }
00304
else
00305 {
00306 filelist << reldir +
"/" + *itt;
00307 }
00308 ++itt;
00309 }
00310
00311
return filelist;
00312 }
00313
00314 void FileGroupsWidget::refresh()
00315 {
00316
while (firstChild())
00317
delete firstChild();
00318
00319
if (
m_actionToggleDisplayLocation->
isChecked()) {
00320
00321
LocationID=addColumn(i18n(
"Location"));
00322 }
00323
else {
00324
00325
00326
if (
LocationID!=-1)
00327 removeColumn(
LocationID);
00328 }
00329
QDomDocument &dom = *
m_part->
projectDom();
00330
DomUtil::PairList list =
00331 DomUtil::readPairListEntry(dom,
"/kdevfileview/groups",
"group",
"name",
"pattern");
00332
00333
FileViewFolderItem *lastGroup = 0;
00334
00335 DomUtil::PairList::ConstIterator git;
00336
for (git = list.begin(); git != list.end(); ++git) {
00337
FileViewFolderItem *newItem =
new FileViewFolderItem(
this, (*git).first, (*git).second);
00338
if (lastGroup)
00339 newItem->moveItem(lastGroup);
00340 lastGroup = newItem;
00341 }
00342
00343
QStringList allFiles;
00344
if (
m_actionToggleShowNonProjectFiles->
isChecked()) {
00345
00346 allFiles =
allFilesRecursively(
m_part->
project()->
projectDirectory() );
00347 }
00348
else {
00349
00350 allFiles =
m_part->
project()->
allFiles();
00351 }
00352 QStringList::ConstIterator fit;
00353
for (fit = allFiles.begin(); fit != allFiles.end(); ++fit) {
00354
QListViewItem *item = firstChild();
00355
while (item) {
00356
FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item);
00357
if (fvgitem->
matches(*fit)) {
00358 (
void)
new FileGroupsFileItem(fvgitem, *fit);
00359
break;
00360 }
00361 item = item->nextSibling();
00362 }
00363 }
00364
00365
QListViewItem *item = firstChild();
00366
while (item) {
00367 item->sortChildItems(0,
true);
00368 item = item->nextSibling();
00369 }
00370 }
00371
00372
00373 void FileGroupsWidget::addFile(
const QString &fileName)
00374 {
00375
kdDebug(9017) <<
"FileView add " << fileName <<
endl;
00376
00377
QListViewItem *item = firstChild();
00378
while (item) {
00379
FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item);
00380
if (fvgitem->
matches(fileName))
00381 {
00382
QString f = fileName;
00383
if (fileName.contains(
m_part->
project()->
projectDirectory()))
00384 f = fileName.mid(
m_part->
project()->
projectDirectory().length()+1);
00385 (
void)
new FileGroupsFileItem(fvgitem, f);
00386 fvgitem->sortChildItems(0,
true);
00387
break;
00388 }
00389 item = item->nextSibling();
00390 }
00391 }
00392
00393 void FileGroupsWidget::addFiles (
const QStringList& fileList )
00394 {
00395 QStringList::ConstIterator it;
00396
00397
for ( it = fileList.begin(); it != fileList.end(); ++it )
00398 {
00399 this->
addFile ( *it );
00400 }
00401 }
00402
00403 void FileGroupsWidget::removeFile(
const QString &fileName)
00404 {
00405
kdDebug(9017) <<
"FileView remove " << fileName <<
endl;
00406
00407
QListViewItem *item = firstChild();
00408
while (item)
00409 {
00410
FileViewFolderItem *fvgitem = static_cast<FileViewFolderItem*>(item);
00411
QListViewItem *childItem = fvgitem->firstChild();
00412
while (childItem)
00413 {
00414
FileGroupsFileItem *fgfitem = static_cast<FileGroupsFileItem*>(childItem);
00415
kdDebug ( 9017 ) <<
"fvfitem->fileName() is " << fgfitem->
fileName() <<
endl;
00416
if (fgfitem->
fileName() == fileName )
00417 {
00418
kdDebug ( 9017 ) <<
"Deleting: " << fgfitem->
fileName() <<
endl;
00419
00420
delete fgfitem;
00421
return;
00422 }
00423 childItem = childItem->nextSibling();
00424 }
00425 item = item->nextSibling();
00426 }
00427 }
00428
00429 void FileGroupsWidget::removeFiles (
const QStringList& fileList )
00430 {
00431 QStringList::ConstIterator it;
00432
00433
for ( it = fileList.begin(); it != fileList.end(); ++it )
00434 {
00435
removeFile ( *it );
00436 }
00437 }
00438
00439 void FileGroupsWidget::slotToggleShowNonProjectFiles()
00440 {
00441
refresh();
00442 }
00443
00444 void FileGroupsWidget::slotToggleDisplayLocation()
00445 {
00446
refresh();
00447 }
00448
00449
00450
#include "filegroupswidget.moc"
00451