diff --git a/projectmanagers/cmake/cmakemanager.cpp b/projectmanagers/cmake/cmakemanager.cpp
index b586f83..b37d045 100644
--- a/projectmanagers/cmake/cmakemanager.cpp
+++ b/projectmanagers/cmake/cmakemanager.cpp
@@ -58,7 +58,6 @@
 #include <language/duchain/duchainlock.h>
 #include <language/duchain/duchainutils.h>
 #include <language/codecompletion/codecompletion.h>
-#include <language/codegen/applychangeswidget.h>
 
 #include "cmakemodelitems.h"
 #include "cmakenavigationwidget.h"
@@ -1052,40 +1051,6 @@ KDevelop::ProjectFolderItem* CMakeManager::addFolder( const KUrl& folder, KDevel
     return 0;
 }
 
-bool CMakeManager::removeFolder( KDevelop::ProjectFolderItem* it)
-{
-    if ( !KDevelop::removeUrl(it->project(), it->url(), true) ) {
-        return false;
-    }
-    
-    if(it->type()!=KDevelop::ProjectBaseItem::BuildFolder) {
-        it->parent()->removeRow(it->row());
-        return true;
-    }
-    
-    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(e.exec())
-    {
-        bool saved=e.applyAllChanges();
-        if(!saved)
-            KMessageBox::error(0, i18n("KDevelop - CMake Support"),
-                                  i18n("Could not save the change."));
-    }
-    return 0;
-}
-
 bool followUses(KTextEditor::Document* doc, RangeInRevision r, const QString& name, const KUrl& lists, bool add, const QString& replace)
 {
     bool ret=false;
@@ -1141,51 +1106,137 @@ bool followUses(KTextEditor::Document* doc, RangeInRevision r, const QString& na
     return ret;
 }
 
-bool CMakeManager::removeFile( KDevelop::ProjectFileItem* it)
+QList<TargetFilePair> CMakeManager::getTargetFilesWithin(const QList<KDevelop::ProjectBaseItem*> &items) const
 {
-    bool ret=true;
-    QList<ProjectFileItem*> files=it->project()->filesForUrl(it->url());
-    QMap<ProjectTargetItem*, ProjectFileItem*> targets;
+    QList<TargetFilePair> targetFiles;
+    foreach (ProjectBaseItem* item, items)
+    {
+        if (ProjectFileItem* file = item->file())
+        {
+            //FIXME: ProjectFileItems should have a list of the targets they belong to
+            QList<ProjectFileItem*> allItemsForUrl = file->project()->filesForUrl(file->url());
+            foreach(ProjectFileItem* item, allItemsForUrl)
+            {
+                if (ProjectTargetItem* target = item->parent()->target())
+                    targetFiles << TargetFilePair(target, item);
+            }
+        }
+        else if (ProjectFolderItem* folder = item->folder())
+            targetFiles += getTargetFilesWithin(folder->children());
+    }
+    return targetFiles;
+}
 
-    //We loop through all the files with the same url
-    foreach(ProjectFileItem* file, files)
+QList<CMakeFolderItem*> CMakeManager::getCMakeFoldersWithin(const QList<KDevelop::ProjectBaseItem*> &items) const
+{
+    QList<CMakeFolderItem*> cmakeFolders;
+    foreach (ProjectBaseItem* item, items)
     {
-        ProjectTargetItem* target=file->parent()->target();
-        if(target)
-            targets.insert(target, file);
+        switch (item->type())
+        {
+        case KDevelop::ProjectBaseItem::BuildFolder:
+            cmakeFolders << static_cast<CMakeFolderItem*>(item);
+            //let it drop
+        case KDevelop::ProjectBaseItem::Folder:
+            getCMakeFoldersWithin(item->children());
+            break;
+        }
     }
-    
-    QMap< ProjectTargetItem*, ProjectFileItem* >::const_iterator it2 = targets.constBegin();
-    for(; it2!=targets.constEnd(); ++it2)
-        ret = ret && removeFileFromTarget(it2.value(), it2.key());
+    return cmakeFolders;
+}
 
-    return ret && KDevelop::removeUrl(it->project(), it->url(), false);
+bool CMakeManager::changesWidgetAddCMakeFolderRemovals(const QList<CMakeFolderItem*> &folders, ApplyChangesWidget* changesWidget)
+{
+    foreach(CMakeFolderItem* folder, folders)
+    {
+        KUrl lists = folder->url().upUrl();
+        lists.addPath("CMakeLists.txt");
+
+        changesWidget->addDocuments(IndexedString(lists));
+        KTextEditor::Range range = folder->descriptor().range().castToSimpleRange().textRange();
+        if (!changesWidget->document()->removeText(range))
+            return false;
+    }
+    return true;
 }
 
-bool CMakeManager::removeFileFromTarget( KDevelop::ProjectFileItem* it, KDevelop::ProjectTargetItem* target)
+bool CMakeManager::changesWidgetAddTargetFileRemovals(const QList<TargetFilePair> &targetFiles, ApplyChangesWidget* changesWidget)
 {
-    if(it->parent()!=target)
-        return false; //It is not a cmake-managed file
+    foreach (TargetFilePair targetFile, targetFiles)
+    {
+        Q_ASSERT(targetFile.second->parent() == targetFile.first);
 
-    CMakeFolderItem* folder=static_cast<CMakeFolderItem*>(target->parent());
+        CMakeFolderItem* folder = static_cast<CMakeFolderItem*>(targetFile.first->parent());
 
-    DescriptorAttatched* desc=dynamic_cast<DescriptorAttatched*>(target);
-    RangeInRevision r=desc->descriptor().range();
-    r.start=CursorInRevision(desc->descriptor().arguments.first().range().end);
+        DescriptorAttatched* desc = dynamic_cast<DescriptorAttatched*>(targetFile.first);
+        RangeInRevision range = desc->descriptor().range();
+        range.start = CursorInRevision(desc->descriptor().arguments.first().range().end);
 
-    KUrl lists=folder->url();
-    lists.addPath("CMakeLists.txt");
+        KUrl lists = folder->url();
+        lists.addPath("CMakeLists.txt");
 
-    ApplyChangesWidget e;
-    e.setCaption(it->text());
-    e.setInformation(i18n("Remove a file called '%1'.", it->text()));
-    e.addDocuments(IndexedString(lists));
+        changesWidget->addDocuments(IndexedString(lists));
 
-    bool ret=followUses(e.document(), r, ' '+it->text(), lists, false, QString());
-    ret &= e.exec();
-    ret &= e.applyAllChanges();
-    
-    return ret;
+        //FIXME: Not sure if this "find" extraction will cover all use cases
+        QString find = KUrl::relativeUrl(folder->url(), targetFile.second->url());
+        if (!followUses(changesWidget->document(), range, ' '+find, lists, false, QString()))
+            return false;
+    }
+    return true;
+}
+
+bool CMakeManager::removeFilesAndFolders( QList<KDevelop::ProjectBaseItem*> items)
+{
+    //First do CMakeLists changes
+    ApplyChangesWidget changesWidget;
+    changesWidget.setCaption(i18n("CMakeLists Changes"));
+    changesWidget.setInformation(i18n("Remove files and folders from CMakeLists as follows:"));
+
+    bool cmakeSuccessful = true;
+    cmakeSuccessful &= changesWidgetAddTargetFileRemovals(getTargetFilesWithin(items), &changesWidget);
+    cmakeSuccessful &= changesWidgetAddCMakeFolderRemovals(getCMakeFoldersWithin(items), &changesWidget);
+
+    if (changesWidget.hasDocuments())
+        cmakeSuccessful &= changesWidget.exec() && changesWidget.applyAllChanges();
+
+    if (!cmakeSuccessful)
+    {
+        if (KMessageBox::questionYesNo( QApplication::activeWindow(),
+                                        i18n("Changes to CMakeLists failed, abort file deletion?"),
+                                        i18n("Error"))
+            == KMessageBox::Yes)
+        {
+            return false;
+        }
+    }
+
+    //Then delete the files/folders
+    foreach(ProjectBaseItem* item, items)
+    {
+        Q_ASSERT(item->folder() || item->file());
+        Q_ASSERT(!item->file() || !item->file()->parent()->target());
+
+        if (!KDevelop::removeUrl(item->project(), item->url(), false))
+            return false;
+    }
+
+    return true;
+}
+
+bool CMakeManager::removeFilesFromTargets( QList<TargetFilePair> targetFiles)
+{
+    ApplyChangesWidget changesWidget;
+    changesWidget.setCaption(i18n("CMakeLists Changes"));
+    changesWidget.setInformation(i18n("Modify project targets as follows:"));
+
+    if (targetFiles.size() &&
+        changesWidgetAddTargetFileRemovals(targetFiles, &changesWidget) &&
+        changesWidget.exec() &&
+        changesWidget.applyAllChanges()) {
+        return true;
+    }
+
+    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..fc0c62b 100644
--- a/projectmanagers/cmake/cmakemanager.h
+++ b/projectmanagers/cmake/cmakemanager.h
@@ -30,6 +30,7 @@
 
 #include <project/interfaces/ibuildsystemmanager.h>
 #include <language/interfaces/ilanguagesupport.h>
+#include <language/codegen/applychangeswidget.h>
 #include <interfaces/iplugin.h>
 #include <interfaces/idocumentationprovider.h>
 
@@ -87,10 +88,9 @@ 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 removeTarget( KDevelop::ProjectTargetItem* ) { return false; }
-    virtual bool removeFile( KDevelop::ProjectFileItem* );
-    virtual bool removeFileFromTarget( KDevelop::ProjectFileItem*, KDevelop::ProjectTargetItem* );
+    virtual bool removeFilesFromTargets( QList<KDevelop::TargetFilePair> );
+    virtual bool removeFilesAndFolders( QList<KDevelop::ProjectBaseItem*> items);
 
     virtual bool renameFile(KDevelop::ProjectFileItem*, const KUrl&);
     virtual bool renameFolder(KDevelop::ProjectFolderItem*, const KUrl&);
@@ -139,6 +139,11 @@ private:
     static void setTargetFiles(KDevelop::ProjectTargetItem* target, const KUrl::List& files);
     void reloadFiles(KDevelop::ProjectFolderItem* item);
 
+    bool changesWidgetAddTargetFileRemovals(const QList<KDevelop::TargetFilePair> &targetFiles, KDevelop::ApplyChangesWidget* changesWidget);
+    bool changesWidgetAddCMakeFolderRemovals(const QList<CMakeFolderItem*> &folders, KDevelop::ApplyChangesWidget* changesWidget);
+    QList<CMakeFolderItem*> getCMakeFoldersWithin(const QList<KDevelop::ProjectBaseItem*> &items) const;
+    QList<KDevelop::TargetFilePair> getTargetFilesWithin(const QList<KDevelop::ProjectBaseItem*> &items) const;
+
     QMap<KDevelop::IProject*, QStringList> m_modulePathPerProject;
     QMap<KDevelop::IProject*, VariableMap> m_varsPerProject;
     QMap<KDevelop::IProject*, MacroMap> m_macrosPerProject;
diff --git a/projectmanagers/custommake/custommakemanager.cpp b/projectmanagers/custommake/custommakemanager.cpp
index a322d18..1ec2664 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,17 @@ ProjectFileItem* CustomMakeManager::addFile(const KUrl& file, KDevelop::ProjectF
     return 0;
 }
 
-bool CustomMakeManager::removeFolder(KDevelop::ProjectFolderItem *folder)
+bool CustomMakeManager::removeFilesAndFolders(QList<KDevelop::ProjectBaseItem*> items)
 {
-    return KDevelop::removeUrl(folder->project(), folder->url(), true);
-}
+    foreach(KDevelop::ProjectBaseItem* item, items)
+    {
+        Q_ASSERT(item->folder() || item->file());
+        Q_ASSERT(!item->file() || !item->file()->parent()->target());
 
-bool CustomMakeManager::removeFile(KDevelop::ProjectFileItem *file)
-{
-    return KDevelop::removeUrl(file->project(), file->url(), false);
+        if (!KDevelop::removeUrl(item->project(), item->url(), false))
+            return false;
+    }
+    return true;
 }
 
 bool CustomMakeManager::renameFile(KDevelop::ProjectFileItem* oldFile, const KUrl& newFile)
diff --git a/projectmanagers/custommake/custommakemanager.h b/projectmanagers/custommake/custommakemanager.h
index 9c1b8a7..9047c9a 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,12 @@ public:
     virtual KDevelop::ProjectFileItem* addFile(const KUrl& file, KDevelop::ProjectFolderItem *parent);
 
     /**
-     * Remove a folder from the project
+     * Remove items from the project and delete them from disk
      *
-     * Removes the folder specified by @p folder from folder @p parent and
+     * Removes the items specified by @p items and
      * modifies the underlying build system if needed.
      */
-    virtual bool removeFolder(KDevelop::ProjectFolderItem *folder);
-
-    /**
-     * Remove a file from the project
-     *
-     * Removes the file specified by @p file and
-     * modifies the underlying build system if needed. If the 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 removeFilesAndFolders( QList<KDevelop::ProjectBaseItem*> items);
 
     /**
      * Rename a file in the project
@@ -181,6 +171,7 @@ public:
     QStringList parseCustomMakeFile( const KUrl &makefile );
 
 private:
+
     class Private;
     Private *d;
 };
