/*************************************************************************** * Copyright (C) 2001-2002 by Bernd Gehrmann * * bernd@kdevelop.org * * * * 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. * * * ***************************************************************************/ #include "filegroupswidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kdevcore.h" #include "kdevproject.h" #include "kdevmainwindow.h" #include "kdevpartcontroller.h" #include "domutil.h" #include "filegroupspart.h" #include "filegroupsconfigwidget.h" // Translations for strings in the project file static const char *translations[] = { I18N_NOOP("Sources"), I18N_NOOP("Translations"), I18N_NOOP("User Interface"), I18N_NOOP("Others") }; class FileComparator { public: virtual ~FileComparator(){ }; virtual bool matches(const TQString& name) const = 0; }; class RegExpComparator : public FileComparator { public: RegExpComparator(const TQString& pattern) : m_exp(pattern, true, true){ } bool matches(const TQString& name) const{ return m_exp.exactMatch(name); } private: const TQRegExp m_exp; }; class EndingComparator : public FileComparator { public: EndingComparator(const TQString& pattern) : m_pattern ( pattern){ } bool matches(const TQString& name) const{ return name.endsWith(m_pattern); } private: const TQString m_pattern; }; class FileViewFolderItem : public TQListViewItem { public: FileViewFolderItem(TQListView *parent, const TQString &name, const TQString &pattern); bool matches(const TQString &fileName); private: TQPtrList m_patterns; }; FileViewFolderItem::FileViewFolderItem(TQListView *parent, const TQString &name, const TQString &pattern) : TQListViewItem(parent, name) { setPixmap(0, SmallIcon("folder")); m_patterns.setAutoDelete(true); TQStringList patternstring = TQStringList::split(';', pattern); TQStringList::ConstIterator theend = patternstring.end(); for (TQStringList::ConstIterator ci = patternstring.begin(); ci != theend; ++ci) { TQString pattern = *ci; TQString tail = pattern.right( pattern.length() - 1 ); if ( (tail).contains('*') || pattern.contains('?') || pattern.contains('[') || pattern.contains(']') ) { m_patterns.append( new RegExpComparator( pattern ) ); } else { if ( pattern.startsWith("*") ) { m_patterns.append( new EndingComparator( tail ) ); } else { m_patterns.append( new EndingComparator( pattern ) ); } } } } bool FileViewFolderItem::matches(const TQString &fileName) { // Test with the file path, so that "*ClientServer/*.h" patterns work TQString fName = TQFileInfo(fileName).filePath(); TQPtrList::ConstIterator theend = m_patterns.end(); for (TQPtrList::ConstIterator ci = m_patterns.begin(); ci != theend; ++ci) if ((*ci)->matches(fName)) return true; return false; } class FileGroupsFileItem : public TQListViewItem { public: FileGroupsFileItem(TQListViewItem *parent, const TQString &fileName); TQString fileName() const { return fullname; } private: TQString fullname; }; FileGroupsFileItem::FileGroupsFileItem(TQListViewItem *parent, const TQString &fileName) : TQListViewItem(parent), fullname(fileName) { setPixmap(0, SmallIcon("text-x-generic")); TQFileInfo fi(fileName); setText(0, fi.fileName()); setText(1, "./" + fi.dirPath()); } FileGroupsWidget::FileGroupsWidget(FileGroupsPart *part) : TDEListView(0, "file view widget"), m_actionToggleShowNonProjectFiles( 0 ), m_actionToggleDisplayLocation( 0 ) { /* Setting Location ID to -1 so I can check if it has been loaded later. If I dont, it will remove the name column and this is not too good :-) Is there any better way to do this? */ LocationID=-1; setFocusPolicy(TQ_ClickFocus); setRootIsDecorated(true); setResizeMode(TQListView::LastColumn); setSorting(-1); addColumn(i18n("Name")); setAllColumnsShowFocus( true ); // addColumn(i18n("Location")); connect( this, TQT_SIGNAL(executed(TQListViewItem*)), this, TQT_SLOT(slotItemExecuted(TQListViewItem*)) ); connect( this, TQT_SIGNAL(returnPressed(TQListViewItem*)), this, TQT_SLOT(slotItemExecuted(TQListViewItem*)) ); connect( this, TQT_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)), this, TQT_SLOT(slotContextMenu(TDEListView*, TQListViewItem*, const TQPoint&)) ); m_actionToggleShowNonProjectFiles = new TDEToggleAction( i18n("Show Non Project Files"), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT(slotToggleShowNonProjectFiles()), TQT_TQOBJECT(this), "actiontoggleshowshownonprojectfiles" ); m_actionToggleShowNonProjectFiles->setCheckedState(i18n("Hide Non Project Files")); m_actionToggleShowNonProjectFiles->setWhatsThis(i18n("Show non project files

Shows files that do not belong to a project in a file tree.")); m_actionToggleDisplayLocation = new TDEToggleAction( i18n("Display Location Column"), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT(slotToggleDisplayLocation()), TQT_TQOBJECT(this), "actiontoggleshowlocation" ); m_actionToggleDisplayLocation->setWhatsThis(i18n("Display the Location Column

Displays a column with the location of the files.")); m_part = part; (void) translations; // supress compiler warning TQDomDocument &dom = *m_part->projectDom(); m_actionToggleShowNonProjectFiles->setChecked( !DomUtil::readBoolEntry(dom, "/kdevfileview/groups/hidenonprojectfiles") ); m_actionToggleDisplayLocation->setChecked( !DomUtil::readBoolEntry(dom, "/kdevfileview/groups/hidenonlocation") ); } FileGroupsWidget::~FileGroupsWidget() { TQDomDocument &dom = *m_part->projectDom(); DomUtil::writeBoolEntry( dom, "/kdevfileview/groups/hidenonprojectfiles", !m_actionToggleShowNonProjectFiles->isChecked() ); DomUtil::writeBoolEntry( dom, "/kdevfileview/groups/hidenonlocation", !m_actionToggleDisplayLocation->isChecked() ); } void FileGroupsWidget::slotItemExecuted(TQListViewItem *item) { if (!item) return; // toggle open state for parents if (item->childCount() > 0) setOpen(item, !isOpen(item)); // Is it a group item? if (!item->parent()) return; FileGroupsFileItem *fgfitem = static_cast(item); m_part->partController()->editDocument(KURL::fromPathOrURL( m_part->project()->projectDirectory() + "/" + fgfitem->fileName() )); } void FileGroupsWidget::slotContextMenu(TDEListView *, TQListViewItem *item, const TQPoint &p) { TDEPopupMenu popup(this); popup.insertTitle(i18n("File Groups")); /// @todo Add, remove groups int customizeId = popup.insertItem(i18n("Customize...")); popup.setWhatsThis(customizeId, i18n("Customize

Opens Customize File Groups dialog where the groups can be managed.")); if (item) { if (item->parent()) { // Not for group items FileGroupsFileItem *fvfitem = static_cast(item); TQString pathName = m_part->project()->projectDirectory() + TQDir::separator() + fvfitem->fileName(); KURL::List urls; urls.append(pathName); FileContext context(urls); m_part->core()->fillContextMenu(&popup, &context); } else{ TQStringList file_list; TQListViewItem* i = item->firstChild(); while(i){ FileGroupsFileItem *fvgitem = static_cast(i); file_list << fvgitem->fileName(); i = i->nextSibling(); } FileContext context(file_list); m_part->core()->fillContextMenu(&popup, &context); } } m_actionToggleShowNonProjectFiles->plug( &popup ); m_actionToggleDisplayLocation->plug( &popup ); int res = popup.exec(p); if (res == customizeId) { KDialogBase dlg(KDialogBase::TreeList, i18n("Customize File Groups"), KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, this, "customization dialog"); TQVBox *vbox = dlg.addVBoxPage(i18n("File Groups")); FileGroupsConfigWidget *w = new FileGroupsConfigWidget(m_part, vbox, "file groups config widget"); connect(&dlg, TQT_SIGNAL(okClicked()), w, TQT_SLOT(accept())); dlg.exec(); } } TQStringList FileGroupsWidget::allFilesRecursively( TQString const & dir ) { TQStringList filelist; TQString reldir = dir.mid( m_part->project()->projectDirectory().length() +1 ); // recursively fetch all files in subdirectories TQStringList subdirs = TQDir( dir ).entryList( TQDir::Dirs ); TQValueListIterator it = subdirs.begin(); while ( it != subdirs.end() ) { if ( *it != "." && *it != ".." ) { filelist += allFilesRecursively( dir + "/"+ *it ); } ++it; } // append the project relative directory path to all files in the current directory TQStringList dirlist = TQDir( dir ).entryList( TQDir::Files ); TQValueListIterator itt = dirlist.begin(); while ( itt != dirlist.end() ) { if ( reldir.isEmpty() ) { filelist << *itt; } else { filelist << reldir + "/" + *itt; } ++itt; } return filelist; } void FileGroupsWidget::refresh() { while (firstChild()) delete firstChild(); if (m_actionToggleDisplayLocation->isChecked()) { // Display the Location column LocationID=addColumn(i18n("Location")); } else { // Remove the Location column //Need to check if the ID exists, if not do nothing!! if (LocationID!=-1) removeColumn(LocationID); } TQDomDocument &dom = *m_part->projectDom(); DomUtil::PairList list = DomUtil::readPairListEntry(dom, "/kdevfileview/groups", "group", "name", "pattern"); FileViewFolderItem *lastGroup = 0; DomUtil::PairList::ConstIterator git; for (git = list.begin(); git != list.end(); ++git) { FileViewFolderItem *newItem = new FileViewFolderItem(this, (*git).first, (*git).second); if (lastGroup) newItem->moveItem(lastGroup); lastGroup = newItem; } TQStringList allFiles; if (m_actionToggleShowNonProjectFiles->isChecked()) { // get all files in the project directory allFiles = allFilesRecursively( m_part->project()->projectDirectory() ); } else { // get all project files allFiles = m_part->project()->allFiles(); } TQStringList::ConstIterator fit; for (fit = allFiles.begin(); fit != allFiles.end(); ++fit) { TQListViewItem *item = firstChild(); while (item) { FileViewFolderItem *fvgitem = static_cast(item); if (fvgitem->matches(*fit)) { (void) new FileGroupsFileItem(fvgitem, *fit); break; } item = item->nextSibling(); } } TQListViewItem *item = firstChild(); while (item) { item->sortChildItems(0, true); item = item->nextSibling(); } } void FileGroupsWidget::addFile(const TQString &fileName) { kdDebug(9017) << "FileView add " << fileName << endl; TQListViewItem *item = firstChild(); while (item) { FileViewFolderItem *fvgitem = static_cast(item); if (fvgitem->matches(fileName)) { TQString f = fileName; if (fileName.contains(m_part->project()->projectDirectory())) f = fileName.mid(m_part->project()->projectDirectory().length()+1); (void) new FileGroupsFileItem(fvgitem, f); // fvgitem->sortChildItems(0, true); break; } item = item->nextSibling(); } } void FileGroupsWidget::addFiles ( const TQStringList& fileList ) { TQStringList::ConstIterator it; for ( it = fileList.begin(); it != fileList.end(); ++it ) { this->addFile ( *it ); } sort(); } void FileGroupsWidget::removeFile(const TQString &fileName) { kdDebug(9017) << "FileView remove " << fileName << endl; TQListViewItem *item = firstChild(); while (item) { FileViewFolderItem *fvgitem = static_cast(item); TQListViewItem *childItem = fvgitem->firstChild(); while (childItem) { FileGroupsFileItem *fgfitem = static_cast(childItem); kdDebug ( 9017 ) << "fvfitem->fileName() is " << fgfitem->fileName() << endl; if (fgfitem->fileName() == fileName ) { kdDebug ( 9017 ) << "Deleting: " << fgfitem->fileName() << endl; delete fgfitem; return; } childItem = childItem->nextSibling(); } item = item->nextSibling(); } } void FileGroupsWidget::removeFiles ( const TQStringList& fileList ) { TQStringList::ConstIterator it; for ( it = fileList.begin(); it != fileList.end(); ++it ) { removeFile ( *it ); } } void FileGroupsWidget::slotToggleShowNonProjectFiles() { refresh(); } void FileGroupsWidget::slotToggleDisplayLocation() { refresh(); } #include "filegroupswidget.moc"