diff --git a/interfaces/iproject.h b/interfaces/iproject.h --- a/interfaces/iproject.h +++ b/interfaces/iproject.h @@ -174,6 +174,9 @@ public Q_SLOTS: /** Make the model to reload */ virtual void reloadModel() = 0; + + /** This method is invoked when the project needs to be closed. */ + virtual void close() = 0; }; } diff --git a/interfaces/iprojectcontroller.h b/interfaces/iprojectcontroller.h --- a/interfaces/iprojectcontroller.h +++ b/interfaces/iprojectcontroller.h @@ -141,6 +141,15 @@ * @returns true if the project could be closed, false otherwise */ virtual void closeProject( IProject* ) = 0; + + /** + * Close all projects + * + * This usually calls closeProject() on all controlled projects + * @sa closeProject() + */ + virtual void closeAllProjects() = 0; + virtual void configureProject( IProject* ) = 0; /// Schedules all files of the @p project for reparsing by @see BackgroundParser diff --git a/plugins/quickopen/tests/bench_quickopen.cpp b/plugins/quickopen/tests/bench_quickopen.cpp --- a/plugins/quickopen/tests/bench_quickopen.cpp +++ b/plugins/quickopen/tests/bench_quickopen.cpp @@ -20,6 +20,9 @@ #include "bench_quickopen.h" +#include +#include + #include #include diff --git a/plugins/quickopen/tests/quickopentestbase.cpp b/plugins/quickopen/tests/quickopentestbase.cpp --- a/plugins/quickopen/tests/quickopentestbase.cpp +++ b/plugins/quickopen/tests/quickopentestbase.cpp @@ -57,7 +57,7 @@ void QuickOpenTestBase::cleanup() { - projectController->clearProjects(); + projectController->closeAllProjects(); core->documentController()->closeAllDocuments(); } diff --git a/shell/project.h b/shell/project.h --- a/shell/project.h +++ b/shell/project.h @@ -97,8 +97,7 @@ */ bool open(const Path &projectFile); - /** This method is invoked when the project needs to be closed. */ - void close(); + void close() override; IProjectFileManager* projectFileManager() const override; IBuildSystemManager* buildSystemManager() const override; diff --git a/shell/projectcontroller.h b/shell/projectcontroller.h --- a/shell/projectcontroller.h +++ b/shell/projectcontroller.h @@ -86,8 +86,6 @@ virtual QItemSelectionModel* projectSelectionModel(); IProject* findProjectByName( const QString& name ) override; IProject* findProjectForUrl( const QUrl& ) const override; - void addProject(IProject*); -// IProject* currentProject() const; bool isProjectNameUsed( const QString& name ) const override; void setDialogProvider(IProjectDialogProvider*); @@ -105,6 +103,7 @@ virtual void abortOpeningProject( IProject* ); void projectImportingFinished( IProject* ); void closeProject( IProject* ) override; + void closeAllProjects() override; void configureProject( IProject* ) override; void reparseProject( IProject* project, bool forceUpdate = false ) override; @@ -122,6 +121,22 @@ Q_SCRIPTABLE QString mapSourceBuild( const QString& path, bool reverse = false, bool fallbackRoot = true ) const; protected: + /** + * Add the existing project @p project to the controller + * + * @note Method is used for testing objectives, consider using openProject() instead! + * @note takes ownership over the project + * + * @sa openProject() + */ + void addProject(IProject* proj); + /** + * Remove the project @p project from the controller + * + * @note Ownership is passed on to the caller + */ + void takeProject(IProject* proj); + virtual void loadSettings( bool projectIsLoaded ); virtual void saveSettings( bool projectIsLoaded ); diff --git a/shell/projectcontroller.cpp b/shell/projectcontroller.cpp --- a/shell/projectcontroller.cpp +++ b/shell/projectcontroller.cpp @@ -70,6 +70,7 @@ #include #include "core.h" +// TODO: Should get rid off this include (should depend on IProject only) #include "project.h" #include "mainwindow.h" #include "shellextension.h" @@ -578,9 +579,7 @@ buildSetModel()->storeToSession( Core::self()->activeSession() ); } - foreach( IProject* project, d->m_projects ) { - closeProject( project ); - } + closeAllProjects(); } void ProjectController::initialize() @@ -887,31 +886,22 @@ connect(proj, &IProject::destroyed, this, [&] { d->unloadAllProjectPlugins(); }); } -void ProjectController::closeProject(IProject* proj_) +void ProjectController::takeProject(IProject* proj) { - if (!proj_) - { + if (!proj) { return; } // loading might have failed - d->m_currentlyOpening.removeAll(proj_->projectFile().toUrl()); - - Project* proj = dynamic_cast( proj_ ); - if( !proj ) - { - qWarning() << "Unknown Project subclass found!"; - return; - } + d->m_currentlyOpening.removeAll(proj->projectFile().toUrl()); d->m_projects.removeAll(proj); emit projectClosing(proj); //Core::self()->saveSettings(); // The project file is being closed. // Now we can save settings for all of the Core // objects including this one!! unloadUnusedProjectPlugins(proj); closeAllOpenedFiles(proj); proj->close(); - proj->deleteLater(); //be safe when deleting if (d->m_projects.isEmpty()) { initializePluginCleanup(proj); @@ -921,7 +911,19 @@ d->saveListOfOpenedProjects(); emit projectClosed(proj); - return; +} + +void ProjectController::closeProject(IProject* proj) +{ + takeProject(proj); + proj->deleteLater(); // be safe when deleting +} + +void ProjectController::closeAllProjects() +{ + foreach (auto project, d->m_projects) { + closeProject(project); + } } void ProjectController::abortOpeningProject(IProject* proj) @@ -968,7 +970,17 @@ void ProjectController::addProject(IProject* project) { - d->m_projects.append( project ); + Q_ASSERT(project); + if (d->m_projects.contains(project)) { + qWarning() << "Project already tracked by this project controller:" << project; + return; + } + + // fake-emit signals so listeners are aware of a new project being added + emit projectAboutToBeOpened(project); + project->setParent(this); + d->m_projects.append(project); + emit projectOpened(project); } QItemSelectionModel* ProjectController::projectSelectionModel() diff --git a/tests/testproject.h b/tests/testproject.h --- a/tests/testproject.h +++ b/tests/testproject.h @@ -60,6 +60,7 @@ QList< ProjectFileItem* > filesForPath(const IndexedString&) const override; QList< ProjectFolderItem* > foldersForPath(const IndexedString&) const override { return QList(); } void reloadModel() override { } + void close() override {} Path projectFile() const override; KSharedConfigPtr projectConfiguration() const override { return m_projectConfiguration; } void addToFileSet( ProjectFileItem* file) override; @@ -86,18 +87,19 @@ class KDEVPLATFORMTESTS_EXPORT TestProjectController : public ProjectController { Q_OBJECT + public: TestProjectController(Core* core) : ProjectController(core) {} IProject* projectAt( int i ) const override { return m_projects.at(i); } int projectCount() const override { return m_projects.count(); } QList projects() const override { return m_projects; } + public: - void addProject(IProject* p); - void takeProject(IProject* p); - void clearProjects(); - void closeProject(IProject* p) override; + using ProjectController::addProject; + using ProjectController::takeProject; void initialize() override; + private: QList m_projects; }; diff --git a/tests/testproject.cpp b/tests/testproject.cpp --- a/tests/testproject.cpp +++ b/tests/testproject.cpp @@ -126,36 +126,6 @@ } } -void TestProjectController::addProject(IProject* p) -{ - emit projectAboutToBeOpened(p); - p->setParent(this); - m_projects << p; - emit projectOpened(p); -} - -void TestProjectController::clearProjects() -{ - foreach(IProject* p, m_projects) { - closeProject(p); - } -} - -void TestProjectController::closeProject(IProject* p) -{ - emit projectClosing(p); - delete p; - m_projects.removeOne(p); - emit projectClosed(p); -} - -void KDevelop::TestProjectController::takeProject(KDevelop::IProject* p) -{ - emit projectClosing(p); - m_projects.removeOne(p); - emit projectClosed(p); -} - void TestProjectController::initialize() { }