diff --git a/projectmanagers/cmake/cmakemanager.cpp b/projectmanagers/cmake/cmakemanager.cpp
index 4720e58..ffb2354 100644
--- a/projectmanagers/cmake/cmakemanager.cpp
+++ b/projectmanagers/cmake/cmakemanager.cpp
@@ -1043,38 +1043,52 @@ KDevelop::ProjectFolderItem* CMakeManager::addFolder( const KUrl& folder, KDevel
     return 0;
 }
 
-bool CMakeManager::removeFolder( KDevelop::ProjectFolderItem* it)
+bool CMakeManager::removeFolders( QList<KDevelop::ProjectFolderItem*> folders)
 {
-    if ( !KDevelop::removeUrl(it->project(), it->url(), true) ) {
-        return false;
-    }
-    
-    if(it->type()!=KDevelop::ProjectBaseItem::BuildFolder) {
-        it->parent()->removeRow(it->row());
-        return true;
+    /* FIXME: this function deletes the folder without respect to files inside
+     * that may be attached to a target. Will have to recurse through those
+     * in order to avoid stale CMakeLists.
+     */
+    ApplyChangesWidget changesWidget;
+    changesWidget.setCaption("Remove folder(s)");
+    changesWidget.setInformation(i18n("Remove folders from CMakeLists as follows:"));
+
+    //first get all the CMakeLists changes
+    bool hasCmakeChanges = false;
+    bool success = true;
+    foreach(KDevelop::ProjectFolderItem* folder, folders)
+    {
+        if(folder->type() == KDevelop::ProjectBaseItem::BuildFolder) {
+            hasCmakeChanges = true;
+            KUrl lists = folder->url().upUrl();
+            lists.addPath("CMakeLists.txt");
+
+            changesWidget.addDocuments(IndexedString(lists));
+            CMakeFolderItem* cmakeFolder = static_cast<CMakeFolderItem*>(folder);
+            KTextEditor::Range range = cmakeFolder->descriptor().range().castToSimpleRange().textRange();
+            changesWidget.document()->removeText(range);
+        }
     }
-    
-    KUrl lists=it->url().upUrl();
-    lists.addPath("CMakeLists.txt");
 
-    ApplyChangesWidget e;
-    e.setCaption(it->text());
-    e.setInformation(i18n("Remove a folder called '%1'.", it->text()));
-    e.addDocuments(IndexedString(lists));
-    
-    CMakeFolderItem* cmit=static_cast<CMakeFolderItem*>(it);
-    KTextEditor::Range r=cmit->descriptor().range().castToSimpleRange().textRange();
-    kDebug(9042) << "For " << lists << " remove " << r;
-    e.document()->removeText(r);
+    if (hasCmakeChanges)
+        success = changesWidget.exec() && changesWidget.applyAllChanges();
 
-    if(e.exec())
+    //if CMakeLists changes were successful, or the user doesn't care that they weren't, delete
+    if(success || KMessageBox::questionYesNo(QApplication::activeWindow(), i18n("Failed to remove one or more folders from CMakeLists, continue deleting folders?")) == KMessageBox::Yes)
     {
-        bool saved=e.applyAllChanges();
-        if(!saved)
-            KMessageBox::error(0, i18n("KDevelop - CMake Support"),
-                                  i18n("Could not save the change."));
+        foreach(KDevelop::ProjectFolderItem* folder, folders)
+        {
+            if (!KDevelop::removeUrl(folder->project(), folder->url(), true))
+                return false;
+
+            if(folder->type() != KDevelop::ProjectBaseItem::BuildFolder)
+                folder->parent()->removeRow(folder->row());
+        }
     }
-    return 0;
+    else
+        return false;
+
+    return true;
 }
 
 bool followUses(KTextEditor::Document* doc, RangeInRevision r, const QString& name, const KUrl& lists, bool add, const QString& replace)
@@ -1132,51 +1146,83 @@ bool followUses(KTextEditor::Document* doc, RangeInRevision r, const QString& na
     return ret;
 }
 
-bool CMakeManager::removeFile( KDevelop::ProjectFileItem* it)
+bool CMakeManager::removeFiles( QList<KDevelop::ProjectFileItem*> files)
 {
-    bool ret=true;
-    QList<ProjectFileItem*> files=it->project()->filesForUrl(it->url());
-    QMap<ProjectTargetItem*, ProjectFileItem*> targets;
+    QList< TargetFilePair > targetFiles;
+    QSet<KUrl> fileUrls;
+    for (int i = files.size() - 1; i >= 0; i--)
+    {
+        ProjectFileItem* file = files[i];
+
+        //make sure we didn't get two projectItems for the the same URL/file
+        //ie, one from under its target and again from its parent folder
+        if (fileUrls.size() > 0 && fileUrls.contains(file->url()))
+        {
+            files.removeAt(i);
+            continue;
+        }
+        else
+            fileUrls.insert(file->url());
+
+        //get all project targets that reference this file
+        QList<ProjectFileItem*> allItemsForUrl = file->project()->filesForUrl(file->url());
+        foreach(ProjectFileItem* item, allItemsForUrl)
+        {
+            ProjectTargetItem* target = item->parent()->target();
+            if(target)
+                targetFiles.append(TargetFilePair(target, item));
+        }
+    }
+
+    if (targetFiles.size() > 0 && !removeFilesFromTargets(targetFiles))
+    {
+        if (KMessageBox::questionYesNo(QApplication::activeWindow(),
+            i18n("Failed to remove one or more files from CMakeLists, continue deleting files?"))
+            == KMessageBox::No)
+            return false;
+    }
 
-    //We loop through all the files with the same url
     foreach(ProjectFileItem* file, files)
     {
-        ProjectTargetItem* target=file->parent()->target();
-        if(target)
-            targets.insert(target, file);
+        if (!KDevelop::removeUrl(file->project(), file->url(), false))
+            return false;
     }
-    
-    QMap< ProjectTargetItem*, ProjectFileItem* >::const_iterator it2 = targets.constBegin();
-    for(; it2!=targets.constEnd(); ++it2)
-        ret = ret && removeFileFromTarget(it2.value(), it2.key());
 
-    return ret && KDevelop::removeUrl(it->project(), it->url(), false);
+    return true;
 }
 
-bool CMakeManager::removeFileFromTarget( KDevelop::ProjectFileItem* it, KDevelop::ProjectTargetItem* target)
+bool CMakeManager::removeFilesFromTargets( QList<TargetFilePair> targetFiles)
 {
-    if(it->parent()!=target)
-        return false; //It is not a cmake-managed file
+    ApplyChangesWidget changeWidget;
+    changeWidget.setCaption(i18n("Remove file(s)"));
+    changeWidget.setInformation(i18n("Modify project targets as follows:"));
 
-    CMakeFolderItem* folder=static_cast<CMakeFolderItem*>(target->parent());
+    foreach (TargetFilePair targetFile, targetFiles)
+    {
+        if(targetFile.first != targetFile.second->parent())
+            return false; //It is not a cmake-managed file
 
-    DescriptorAttatched* desc=dynamic_cast<DescriptorAttatched*>(target);
-    RangeInRevision r=desc->descriptor().range();
-    r.start=CursorInRevision(desc->descriptor().arguments.first().range().end);
+        CMakeFolderItem* folder = static_cast<CMakeFolderItem*>(targetFile.first->parent());
 
-    KUrl lists=folder->url();
-    lists.addPath("CMakeLists.txt");
+        DescriptorAttatched* desc = dynamic_cast<DescriptorAttatched*>(targetFile.first);
+        RangeInRevision range = desc->descriptor().range();
+        range.start = CursorInRevision(desc->descriptor().arguments.first().range().end);
 
-    ApplyChangesWidget e;
-    e.setCaption(it->text());
-    e.setInformation(i18n("Remove a file called '%1'.", it->text()));
-    e.addDocuments(IndexedString(lists));
+        KUrl lists = folder->url();
+        lists.addPath("CMakeLists.txt");
 
-    bool ret=followUses(e.document(), r, ' '+it->text(), lists, false, QString());
-    ret &= e.exec();
-    ret &= e.applyAllChanges();
-    
-    return ret;
+        changeWidget.addDocuments(IndexedString(lists));
+
+        //FIXME: Not sure if this "find" extraction will cover all use cases
+        QString find = KUrl::relativeUrl(folder->url(), targetFile.second->url());
+        if (!followUses(changeWidget.document(), range, ' '+find, lists, false, QString()))
+            return false;
+    }
+
+    if (targetFiles.size() && changeWidget.exec() && changeWidget.applyAllChanges())
+        return true;
+    else
+        return false;
 }
 
 //This is being called from ::parse() so we shouldn't make it block the ui
diff --git a/projectmanagers/cmake/cmakemanager.h b/projectmanagers/cmake/cmakemanager.h
index 2fbed7c..377ac49 100644
--- a/projectmanagers/cmake/cmakemanager.h
+++ b/projectmanagers/cmake/cmakemanager.h
@@ -87,10 +87,11 @@ public:
     virtual KDevelop::ProjectTargetItem* createTarget( const QString&, KDevelop::ProjectFolderItem* ) { return 0; }
     virtual bool addFileToTarget( KDevelop::ProjectFileItem*, KDevelop::ProjectTargetItem* );
 
-    virtual bool removeFolder( KDevelop::ProjectFolderItem* );
+    virtual bool removeFolders( QList<KDevelop::ProjectFolderItem*> );
     virtual bool removeTarget( KDevelop::ProjectTargetItem* ) { return false; }
-    virtual bool removeFile( KDevelop::ProjectFileItem* );
-    virtual bool removeFileFromTarget( KDevelop::ProjectFileItem*, KDevelop::ProjectTargetItem* );
+
+    virtual bool removeFiles( QList<KDevelop::ProjectFileItem*> );
+    virtual bool removeFilesFromTargets( QList<KDevelop::TargetFilePair> );
 
     virtual bool renameFile(KDevelop::ProjectFileItem*, const KUrl&);
     virtual bool renameFolder(KDevelop::ProjectFolderItem*, const KUrl&);
diff --git a/projectmanagers/custommake/custommakemanager.cpp b/projectmanagers/custommake/custommakemanager.cpp
index a322d18..b9f5e47 100644
--- a/projectmanagers/custommake/custommakemanager.cpp
+++ b/projectmanagers/custommake/custommakemanager.cpp
@@ -105,10 +105,9 @@ bool CustomMakeManager::removeTarget(KDevelop::ProjectTargetItem *target)
     return false;
 }
 
-bool CustomMakeManager::removeFileFromTarget(KDevelop::ProjectFileItem *file, KDevelop::ProjectTargetItem *parent)
+bool CustomMakeManager::removeFilesFromTargets(QList< TargetFilePair > targetFiles)
 {
-    Q_UNUSED( file )
-    Q_UNUSED( parent )
+    Q_UNUSED( targetFiles )
     return false;
 }
 
@@ -223,14 +222,24 @@ ProjectFileItem* CustomMakeManager::addFile(const KUrl& file, KDevelop::ProjectF
     return 0;
 }
 
-bool CustomMakeManager::removeFolder(KDevelop::ProjectFolderItem *folder)
+bool CustomMakeManager::removeFolders(QList< ProjectFolderItem* > folders)
+{
+    return removeFilesOrFolders(folders);
+}
+
+bool CustomMakeManager::removeFiles(QList<KDevelop::ProjectFileItem*> files)
 {
-    return KDevelop::removeUrl(folder->project(), folder->url(), true);
+    return removeFilesOrFolders(files);
 }
 
-bool CustomMakeManager::removeFile(KDevelop::ProjectFileItem *file)
+template<class T> bool CustomMakeManager::removeFilesOrFolders(QList< T* > items)
 {
-    return KDevelop::removeUrl(file->project(), file->url(), false);
+    bool ret = true;
+    foreach(KDevelop::ProjectBaseItem* item, items)
+    {
+        ret &= KDevelop::removeUrl(item->project(), item->url(), false);
+    }
+    return ret;
 }
 
 bool CustomMakeManager::renameFile(KDevelop::ProjectFileItem* oldFile, const KUrl& newFile)
diff --git a/projectmanagers/custommake/custommakemanager.h b/projectmanagers/custommake/custommakemanager.h
index 9c1b8a7..7684dec 100644
--- a/projectmanagers/custommake/custommakemanager.h
+++ b/projectmanagers/custommake/custommakemanager.h
@@ -89,8 +89,7 @@ public:
      * modifies the underlying build system if needed. The file is not removed
      * from the folder it is in
      */
-    virtual bool removeFileFromTarget(KDevelop::ProjectFileItem *file,
-                                      KDevelop::ProjectTargetItem *parent);
+    virtual bool removeFilesFromTargets(QList<KDevelop::TargetFilePair>);
 
     /**
      * Get the toplevel build directory for the project
@@ -142,21 +141,21 @@ public:
     virtual KDevelop::ProjectFileItem* addFile(const KUrl& file, KDevelop::ProjectFolderItem *parent);
 
     /**
-     * Remove a folder from the project
+     * Remove folders from the project
      *
-     * Removes the folder specified by @p folder from folder @p parent and
+     * Removes the folders specified by @p folders and
      * modifies the underlying build system if needed.
      */
-    virtual bool removeFolder(KDevelop::ProjectFolderItem *folder);
+    virtual bool removeFolders(QList<KDevelop::ProjectFolderItem*> folders);
 
     /**
-     * Remove a file from the project
+     * Remove files from the project
      *
-     * Removes the file specified by @p file and
-     * modifies the underlying build system if needed. If the file being
+     * Removes the files specified by @p files and
+     * modifies the underlying build system if needed. If a file being
      * removed is also part of a target, it should be removed from the target as well
      */
-    virtual bool removeFile(KDevelop::ProjectFileItem *file);
+    virtual bool removeFiles(QList<KDevelop::ProjectFileItem*> files);
 
     /**
      * Rename a file in the project
@@ -181,6 +180,10 @@ public:
     QStringList parseCustomMakeFile( const KUrl &makefile );
 
 private:
+
+    ///Common remove function for files and folders
+    template<class T> bool removeFilesOrFolders(QList<T*> items);
+
     class Private;
     Private *d;
 };
