diff --git a/plugins/execute/executeplugin.cpp b/plugins/execute/executeplugin.cpp index 817c082b8f..5454726a97 100644 --- a/plugins/execute/executeplugin.cpp +++ b/plugins/execute/executeplugin.cpp @@ -1,253 +1,254 @@ /* * This file is part of KDevelop * * Copyright 2007 Hamish Rodda * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "executeplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nativeappconfig.h" #include #include #include #include QString ExecutePlugin::_nativeAppConfigTypeId = "Native Application"; QString ExecutePlugin::workingDirEntry = "Working Directory"; QString ExecutePlugin::executableEntry = "Executable"; QString ExecutePlugin::argumentsEntry = "Arguments"; QString ExecutePlugin::isExecutableEntry = "isExecutable"; QString ExecutePlugin::dependencyEntry = "Dependencies"; QString ExecutePlugin::environmentGroupEntry = "EnvironmentGroup"; QString ExecutePlugin::useTerminalEntry = "Use External Terminal"; QString ExecutePlugin::terminalEntry = "External Terminal"; QString ExecutePlugin::userIdToRunEntry = "User Id to Run"; QString ExecutePlugin::dependencyActionEntry = "Dependency Action"; QString ExecutePlugin::projectTargetEntry = "Project Target"; using namespace KDevelop; K_PLUGIN_FACTORY(KDevExecuteFactory, registerPlugin(); ) K_EXPORT_PLUGIN(KDevExecuteFactory(KAboutData("kdevexecute", "kdevexecute", ki18n("Execute support"), "0.1", ki18n("Allows running of native apps"), KAboutData::License_GPL))) ExecutePlugin::ExecutePlugin(QObject *parent, const QVariantList&) : KDevelop::IPlugin(KDevExecuteFactory::componentData(), parent) { KDEV_USE_EXTENSION_INTERFACE( IExecutePlugin ) m_configType = new NativeAppConfigType(); m_configType->addLauncher( new NativeAppLauncher() ); kDebug() << "adding native app launch config"; core()->runController()->addConfigurationType( m_configType ); } ExecutePlugin::~ExecutePlugin() { } void ExecutePlugin::unload() { core()->runController()->removeConfigurationType( m_configType ); delete m_configType; m_configType = 0; } QStringList ExecutePlugin::arguments( KDevelop::ILaunchConfiguration* cfg, QString& err_ ) const { if( !cfg ) { return QStringList(); } KShell::Errors err; QStringList args = KShell::splitArgs( cfg->config().readEntry( ExecutePlugin::argumentsEntry, "" ), KShell::TildeExpand | KShell::AbortOnMeta, &err ); if( err != KShell::NoError ) { if( err == KShell::BadQuoting ) { err_ = i18n("There is a quoting error in the arguments for " "the launch configuration '%1'. Aborting start.", cfg->name() ); } else { err_ = i18n("A shell meta character was included in the " "arguments for the launch configuration '%1', " "this is not supported currently. Aborting start.", cfg->name() ); } args = QStringList(); kWarning() << "Launch Configuration:" << cfg->name() << "arguments have meta characters"; } return args; } KJob* ExecutePlugin::dependecyJob( KDevelop::ILaunchConfiguration* cfg ) const { QVariantList deps = KDevelop::stringToQVariant( cfg->config().readEntry( dependencyEntry, QString() ) ).toList(); QString depAction = cfg->config().readEntry( dependencyActionEntry, "Nothing" ); if( depAction != "Nothing" && !deps.isEmpty() ) { KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel(); QList items; foreach( const QVariant& dep, deps ) { KDevelop::ProjectBaseItem* item = model->itemFromIndex( model->pathToIndex( dep.toStringList() ) ); if( item ) { items << item; } else { KMessageBox::error(core()->uiController()->activeMainWindow(), i18n("Couldn't resolve the dependency: %1", dep.toString())); } } KDevelop::BuilderJob* job = new KDevelop::BuilderJob(); if( depAction == "Build" ) { job->addItems( KDevelop::BuilderJob::Build, items ); } else if( depAction == "Install" ) { job->addItems( KDevelop::BuilderJob::Install, items ); } + job->updateJobName(); return job; } return 0; } QString ExecutePlugin::environmentGroup( KDevelop::ILaunchConfiguration* cfg ) const { if( !cfg ) { return ""; } return cfg->config().readEntry( ExecutePlugin::environmentGroupEntry, "" ); } KUrl ExecutePlugin::executable( KDevelop::ILaunchConfiguration* cfg, QString& err ) const { KUrl executable; if( !cfg ) { return executable; } KConfigGroup grp = cfg->config(); if( grp.readEntry(ExecutePlugin::isExecutableEntry, false ) ) { executable = grp.readEntry( ExecutePlugin::executableEntry, KUrl("") ); } else { QStringList prjitem = grp.readEntry( ExecutePlugin::projectTargetEntry, QStringList() ); KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel(); KDevelop::ProjectBaseItem* item = dynamic_cast( model->itemFromIndex( model->pathToIndex(prjitem) ) ); if( item && item->executable() ) { // TODO: Need an option in the gui to choose between installed and builddir url here, currently cmake only supports builddir url executable = item->executable()->builtUrl(); } } if( executable.isEmpty() ) { err = i18n("No valid executable specified"); kWarning() << "Launch Configuration:" << cfg->name() << "no valid executable set"; } else { KShell::Errors err_; if( KShell::splitArgs( executable.toLocalFile(), KShell::TildeExpand | KShell::AbortOnMeta, &err_ ).isEmpty() || err_ != KShell::NoError ) { executable = KUrl(); if( err_ == KShell::BadQuoting ) { err = i18n("There is a quoting error in the executable " "for the launch configuration '%1'. " "Aborting start.", cfg->name() ); } else { err = i18n("A shell meta character was included in the " "executable for the launch configuration '%1', " "this is not supported currently. Aborting start.", cfg->name() ); } kWarning() << "Launch Configuration:" << cfg->name() << "executable has meta characters"; } } return executable; } bool ExecutePlugin::useTerminal( KDevelop::ILaunchConfiguration* cfg ) const { if( !cfg ) { return false; } return cfg->config().readEntry( ExecutePlugin::useTerminalEntry, false ); } QString ExecutePlugin::terminal( KDevelop::ILaunchConfiguration* cfg ) const { if( !cfg ) { return QString(); } return cfg->config().readEntry( ExecutePlugin::terminalEntry, QString() ); } KUrl ExecutePlugin::workingDirectory( KDevelop::ILaunchConfiguration* cfg ) const { if( !cfg ) { return KUrl(); } return cfg->config().readEntry( ExecutePlugin::workingDirEntry, KUrl() ); } QString ExecutePlugin::nativeAppConfigTypeId() const { return _nativeAppConfigTypeId; } #include "executeplugin.moc" diff --git a/plugins/projectmanagerview/CMakeLists.txt b/plugins/projectmanagerview/CMakeLists.txt index 3719dc7875..aec8360bd6 100644 --- a/plugins/projectmanagerview/CMakeLists.txt +++ b/plugins/projectmanagerview/CMakeLists.txt @@ -1,29 +1,28 @@ add_definitions( -DKDE_DEFAULT_DEBUG_AREA=9511 ) ########### next target ############### set(kdevprojectmanagerview_PLUGIN_SRCS projectmanagerviewplugin.cpp projectmanagerview.cpp projectmodelsaver.cpp projecttreeview.cpp projectbuildsetwidget.cpp - builditembuilderjob.cpp ) kde4_add_ui_files( kdevprojectmanagerview_PLUGIN_SRCS projectbuildsetwidget.ui projectmanagerview.ui ) kde4_add_plugin(kdevprojectmanagerview ${kdevprojectmanagerview_PLUGIN_SRCS}) target_link_libraries(kdevprojectmanagerview ${KDE4_KDEUI_LIBS} ${KDE4_KTEXTEDITOR_LIBS} kdevplatforminterfaces kdevplatformproject kdevplatformlanguage kdevplatformutil sublime ${KDE4_THREADWEAVER_LIBRARIES} ) install(TARGETS kdevprojectmanagerview DESTINATION ${PLUGIN_INSTALL_DIR} ) ########### install files ############### install( FILES kdevprojectmanagerview.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) install( FILES kdevprojectmanagerview.rc DESTINATION ${DATA_INSTALL_DIR}/kdevprojectmanagerview ) diff --git a/plugins/projectmanagerview/builditembuilderjob.cpp b/plugins/projectmanagerview/builditembuilderjob.cpp deleted file mode 100644 index d5e75d0363..0000000000 --- a/plugins/projectmanagerview/builditembuilderjob.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************** - * This file is part of KDevelop * - * Copyright 2007 Andreas Pakulat * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU Library General Public License as * - * published by the Free Software Foundation; either version 2 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ - -#include "builditembuilderjob.h" - -#include -#include -#include - -BuildItemBuilderJob::BuildItemBuilderJob( KDevelop::BuilderJob::BuildType t, const QList& items ) -{ - foreach( const KDevelop::BuildItem &item, items ) - { - KDevelop::ProjectBaseItem *it=item.findItem(); - //FIXME: should have disabled the building before - //convert to assert or remove "if(it)" when it's done - if(it) - addItem( t, it ); - } - -} - -BuildItemBuilderJob::BuildItemBuilderJob( KDevelop::BuilderJob::BuildType t, const QList& items ) -{ - addItems( t, items ); -} - -BuildItemBuilderJob::BuildItemBuilderJob( KDevelop::BuilderJob::BuildType t, const QList& projects ) -{ - addProjects( t, projects ); -} - -#include "builditembuilderjob.moc" diff --git a/plugins/projectmanagerview/builditembuilderjob.h b/plugins/projectmanagerview/builditembuilderjob.h deleted file mode 100644 index 20ea87da15..0000000000 --- a/plugins/projectmanagerview/builditembuilderjob.h +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************** - * This file is part of KDevelop * - * Copyright 2007 Andreas Pakulat * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU Library General Public License as * - * published by the Free Software Foundation; either version 2 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ - -#ifndef BUILDITEM_BUILDERJOB_H -#define BUILDITEM_BUILDERJOB_H - -#include - -#include - -namespace KDevelop -{ -class ProjectBaseItem; -class IProject; -class BuildItem; -} - -class BuildItemBuilderJob : public KDevelop::BuilderJob -{ - Q_OBJECT -public: - BuildItemBuilderJob( KDevelop::BuilderJob::BuildType, const QList& ); - BuildItemBuilderJob( KDevelop::BuilderJob::BuildType, const QList& items ); - BuildItemBuilderJob( KDevelop::BuilderJob::BuildType, const QList& items ); -}; - -#endif - -//kate: space-indent on; indent-width 4; replace-tabs on; auto-insert-doxygen on; indent-mode cstyle; diff --git a/plugins/projectmanagerview/projectmanagerviewplugin.cpp b/plugins/projectmanagerview/projectmanagerviewplugin.cpp index 968376d749..601dbc40f0 100644 --- a/plugins/projectmanagerview/projectmanagerviewplugin.cpp +++ b/plugins/projectmanagerview/projectmanagerviewplugin.cpp @@ -1,607 +1,629 @@ /* This file is part of KDevelop Copyright 2004 Roberto Raggi Copyright 2007 Andreas Pakulat This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "projectmanagerviewplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "projectmanagerview.h" -#include "builditembuilderjob.h" using namespace KDevelop; K_PLUGIN_FACTORY(ProjectManagerFactory, registerPlugin(); ) K_EXPORT_PLUGIN(ProjectManagerFactory(KAboutData("kdevprojectmanagerview","kdevprojectmanagerview", ki18n("Project Management View"), "0.1", ki18n("Toolview to do all the project management stuff"), KAboutData::License_GPL))) class KDevProjectManagerViewFactory: public KDevelop::IToolViewFactory { public: KDevProjectManagerViewFactory( ProjectManagerViewPlugin *plugin ): mplugin( plugin ) {} virtual QWidget* create( QWidget *parent = 0 ) { return new ProjectManagerView( mplugin, parent ); } virtual Qt::DockWidgetArea defaultPosition() { return Qt::LeftDockWidgetArea; } virtual QString id() const { return "org.kdevelop.ProjectsView"; } virtual QList< QAction* > contextMenuActions(QWidget* viewWidget) const { QList actions; foreach(QAction* action, viewWidget->actions()) { if (!qobject_cast(action)) { actions << action; } } return actions; } private: ProjectManagerViewPlugin *mplugin; }; class ProjectManagerViewPluginPrivate { public: ProjectManagerViewPluginPrivate() {} KDevProjectManagerViewFactory *factory; QList ctxProjectItemList; KAction* m_buildAll; KAction* m_build; KAction* m_install; KAction* m_clean; KAction* m_configure; KAction* m_prune; }; ProjectManagerViewPlugin::ProjectManagerViewPlugin( QObject *parent, const QVariantList& ) : IPlugin( ProjectManagerFactory::componentData(), parent ), d(new ProjectManagerViewPluginPrivate) { d->m_buildAll = new KAction( i18n("Build all Projects"), this ); d->m_buildAll->setIcon(KIcon("run-build")); connect( d->m_buildAll, SIGNAL(triggered()), this, SLOT(buildAllProjects()) ); actionCollection()->addAction( "project_buildall", d->m_buildAll ); d->m_build = new KAction( i18n("Build Selection"), this ); d->m_build->setIconText( i18n("Build") ); d->m_build->setShortcut( Qt::Key_F8 ); d->m_build->setIcon(KIcon("run-build")); d->m_build->setEnabled( false ); connect( d->m_build, SIGNAL(triggered()), this, SLOT(buildProjectItems()) ); actionCollection()->addAction( "project_build", d->m_build ); d->m_install = new KAction( i18n("Install Selection"), this ); d->m_install->setIconText( i18n("Install") ); d->m_install->setIcon(KIcon("run-build-install")); d->m_install->setEnabled( false ); connect( d->m_install, SIGNAL(triggered()), this, SLOT(installProjectItems()) ); actionCollection()->addAction( "project_install", d->m_install ); d->m_clean = new KAction( i18n("Clean Selection"), this ); d->m_clean->setIconText( i18n("Clean") ); d->m_clean->setIcon(KIcon("run-build-clean")); d->m_clean->setEnabled( false ); connect( d->m_clean, SIGNAL(triggered()), this, SLOT(cleanProjectItems()) ); actionCollection()->addAction( "project_clean", d->m_clean ); d->m_configure = new KAction( i18n("Configure Selection"), this ); d->m_configure->setIconText( i18n("Configure") ); d->m_configure->setIcon(KIcon("run-build-configure")); d->m_configure->setEnabled( false ); connect( d->m_configure, SIGNAL(triggered()), this, SLOT(configureProjectItems()) ); actionCollection()->addAction( "project_configure", d->m_configure ); d->m_prune = new KAction( i18n("Prune Selection"), this ); d->m_prune->setIconText( i18n("Prune") ); d->m_prune->setIcon(KIcon("run-build-prune")); d->m_prune->setEnabled( false ); connect( d->m_prune, SIGNAL(triggered()), this, SLOT(pruneProjectItems()) ); actionCollection()->addAction( "project_prune", d->m_prune ); // only add the action so that its known in the actionCollection // and so that it's shortcut etc. pp. is restored // apparently that is not possible to be done in the view itself *sigh* actionCollection()->addAction( "locate_document" ); setXMLFile( "kdevprojectmanagerview.rc" ); d->factory = new KDevProjectManagerViewFactory( this ); core()->uiController()->addToolView( i18n("Projects"), d->factory ); connect( core()->selectionController(), SIGNAL(selectionChanged(KDevelop::Context*)), SLOT(updateActionState(KDevelop::Context*))); connect( ICore::self()->projectController()->buildSetModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(updateFromBuildSetChange())); connect( ICore::self()->projectController()->buildSetModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(updateFromBuildSetChange())); connect( ICore::self()->projectController()->buildSetModel(), SIGNAL(modelReset()), SLOT(updateFromBuildSetChange())); } void ProjectManagerViewPlugin::updateFromBuildSetChange() { updateActionState( core()->selectionController()->currentSelection() ); } void ProjectManagerViewPlugin::updateActionState( KDevelop::Context* ctx ) { bool isEmpty = ICore::self()->projectController()->buildSetModel()->items().isEmpty(); if( isEmpty ) { isEmpty = !ctx || ctx->type() != Context::ProjectItemContext || dynamic_cast( ctx )->items().isEmpty(); } d->m_build->setEnabled( !isEmpty ); d->m_install->setEnabled( !isEmpty ); d->m_clean->setEnabled( !isEmpty ); d->m_configure->setEnabled( !isEmpty ); d->m_prune->setEnabled( !isEmpty ); } ProjectManagerViewPlugin::~ProjectManagerViewPlugin() { delete d; } void ProjectManagerViewPlugin::unload() { kDebug() << "unloading manager view"; core()->uiController()->removeToolView(d->factory); } ContextMenuExtension ProjectManagerViewPlugin::contextMenuExtension( KDevelop::Context* context ) { d->ctxProjectItemList.clear(); if( context->type() != KDevelop::Context::ProjectItemContext ) return IPlugin::contextMenuExtension( context ); KDevelop::ProjectItemContext* ctx = dynamic_cast( context ); QList items = ctx->items(); if( items.isEmpty() ) return IPlugin::contextMenuExtension( context ); //TODO: also needs: removeTarget, removeFileFromTarget, runTargetsFromContextMenu ContextMenuExtension menuExt; bool needsCreateFile = true; bool needsCreateFolder = true; bool needsCloseProjects = true; bool needsBuildItems = true; bool needsFolderItems = true; bool needsRemoveAndRename = true; bool needsRemoveTargetFiles = true; //needsCreateFile if there is one item and it's a folder or target needsCreateFile &= (items.count() == 1) && (items.first()->folder() || items.first()->target()); //needsCreateFolder if there is one item and it's a folder needsCreateFolder &= (items.count() == 1) && (items.first()->folder()); foreach( ProjectBaseItem* item, items ) { d->ctxProjectItemList << item; //needsBuildItems if items are limited to targets and buildfolders needsBuildItems &= item->target() || item->type() == ProjectBaseItem::BuildFolder; //needsCloseProjects if items are limited to top level folders (Project Folders) needsCloseProjects &= item->folder() && !item->folder()->parent(); //needsFolderItems if items are limited to folders needsFolderItems &= (bool)item->folder(); //needsRemove if items are limited to non-top-level folders or files that don't belong to targets needsRemoveAndRename &= (item->folder() && item->parent()) || (item->file() && !item->parent()->target()); //needsRemoveTargets if items are limited to file items with target parents needsRemoveTargetFiles &= (item->file() && item->parent()->target()); } if ( needsCreateFile ) { KAction* action = new KAction( i18n( "Create File" ), this ); action->setIcon(KIcon("document-new")); connect( action, SIGNAL(triggered()), this, SLOT(createFileFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::FileGroup, action ); } if ( needsCreateFolder ) { KAction* action = new KAction( i18n( "Create Folder" ), this ); action->setIcon(KIcon("folder-new")); connect( action, SIGNAL(triggered()), this, SLOT(createFolderFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::FileGroup, action ); } if ( needsBuildItems ) { KAction* action = new KAction( i18nc( "@action", "Build" ), this ); action->setIcon(KIcon("run-build")); connect( action, SIGNAL(triggered()), this, SLOT(buildItemsFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::BuildGroup, action ); action = new KAction( i18nc( "@action", "Install" ), this ); action->setIcon(KIcon("run-install")); connect( action, SIGNAL(triggered()), this, SLOT(installItemsFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::BuildGroup, action ); action = new KAction( i18nc( "@action", "Clean" ), this ); action->setIcon(KIcon("run-clean")); connect( action, SIGNAL(triggered()), this, SLOT(cleanItemsFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::BuildGroup, action ); action = new KAction( i18n( "Add to Buildset" ), this ); connect( action, SIGNAL(triggered()), this, SLOT(addItemsFromContextMenuToBuildset()) ); menuExt.addAction( ContextMenuExtension::BuildGroup, action ); } if ( needsCloseProjects ) { KAction* close = new KAction( i18np( "Close Project", "Close Projects", items.count() ), this ); close->setIcon(KIcon("project-development-close")); connect( close, SIGNAL(triggered()), this, SLOT(closeProjects()) ); menuExt.addAction( ContextMenuExtension::ProjectGroup, close ); } if ( needsFolderItems ) { KAction* action = new KAction( i18n( "Reload" ), this ); action->setIcon(KIcon("view-refresh")); connect( action, SIGNAL(triggered()), this, SLOT(reloadFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::FileGroup, action ); } if ( needsRemoveAndRename ) { KAction* remove = new KAction( i18n( "Remove" ), this ); remove->setIcon(KIcon("user-trash")); connect( remove, SIGNAL(triggered()), this, SLOT(removeFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::FileGroup, remove ); KAction* rename = new KAction( i18n( "Rename" ), this ); rename->setIcon(KIcon("edit-rename")); connect( rename, SIGNAL(triggered()), this, SLOT(renameItemFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::FileGroup, rename ); } if ( needsRemoveTargetFiles ) { KAction* remove = new KAction( i18n( "Remove From Target" ), this ); remove->setIcon(KIcon("user-trash")); connect( remove, SIGNAL(triggered()), this, SLOT(removeTargetFilesFromContextMenu()) ); menuExt.addAction( ContextMenuExtension::FileGroup, remove ); } return menuExt; } void ProjectManagerViewPlugin::closeProjects() { QList projectsToClose; foreach( KDevelop::ProjectBaseItem* item, d->ctxProjectItemList ) { if( !projectsToClose.contains( item->project() ) ) { projectsToClose << item->project(); } } d->ctxProjectItemList.clear(); foreach( KDevelop::IProject* proj, projectsToClose ) { core()->projectController()->closeProject( proj ); } } void ProjectManagerViewPlugin::installItemsFromContextMenu() { - ICore::self()->runController()->registerJob( new BuildItemBuilderJob( KDevelop::BuilderJob::Install, d->ctxProjectItemList ) ); + runBuilderJob( BuilderJob::Install, d->ctxProjectItemList ); d->ctxProjectItemList.clear(); } void ProjectManagerViewPlugin::cleanItemsFromContextMenu() { - ICore::self()->runController()->registerJob( new BuildItemBuilderJob( KDevelop::BuilderJob::Clean, d->ctxProjectItemList ) ); + runBuilderJob( BuilderJob::Clean, d->ctxProjectItemList ); d->ctxProjectItemList.clear(); } void ProjectManagerViewPlugin::buildItemsFromContextMenu() { - ICore::self()->runController()->registerJob( new BuildItemBuilderJob( KDevelop::BuilderJob::Build, d->ctxProjectItemList ) ); + runBuilderJob( BuilderJob::Build, d->ctxProjectItemList ); d->ctxProjectItemList.clear(); } -void ProjectManagerViewPlugin::buildAllProjects() +QList ProjectManagerViewPlugin::collectAllProjects() { QList items; foreach( KDevelop::IProject* project, core()->projectController()->projects() ) { items << project->projectItem(); } - ICore::self()->runController()->registerJob( new BuildItemBuilderJob( KDevelop::BuilderJob::Build, items ) ); + return items; } -void ProjectManagerViewPlugin::runBuilderJob( KDevelop::BuilderJob::BuildType t ) +void ProjectManagerViewPlugin::buildAllProjects() +{ + runBuilderJob( BuilderJob::Build, collectAllProjects() ); +} + +QList ProjectManagerViewPlugin::collectItems() { QList items; - if( !ICore::self()->projectController()->buildSetModel()->items().isEmpty() ) + QList buildItems = ICore::self()->projectController()->buildSetModel()->items(); + if( !buildItems.isEmpty() ) { - ICore::self()->runController()->registerJob( new BuildItemBuilderJob( t, ICore::self()->projectController()->buildSetModel()->items() ) ); + foreach( const BuildItem& buildItem, buildItems ) + { + if( ProjectBaseItem* item = buildItem.findItem() ) + { + items << item; + } + } + } else { KDevelop::ProjectItemContext* ctx = dynamic_cast(ICore::self()->selectionController()->currentSelection()); - ICore::self()->runController()->registerJob( new BuildItemBuilderJob( t, ctx->items() ) ); + items = ctx->items(); } + + return items; +} + +void ProjectManagerViewPlugin::runBuilderJob( BuilderJob::BuildType type, QList items ) +{ + BuilderJob* builder = new BuilderJob; + builder->addItems( type, items ); + builder->updateJobName(); + ICore::self()->runController()->registerJob( builder ); } void ProjectManagerViewPlugin::installProjectItems() { - runBuilderJob( KDevelop::BuilderJob::Install ); + runBuilderJob( KDevelop::BuilderJob::Install, collectItems() ); } void ProjectManagerViewPlugin::pruneProjectItems() { - runBuilderJob( KDevelop::BuilderJob::Prune ); + runBuilderJob( KDevelop::BuilderJob::Prune, collectItems() ); } void ProjectManagerViewPlugin::configureProjectItems() { - runBuilderJob( KDevelop::BuilderJob::Configure ); + runBuilderJob( KDevelop::BuilderJob::Configure, collectItems() ); } void ProjectManagerViewPlugin::cleanProjectItems() { - runBuilderJob( KDevelop::BuilderJob::Clean ); + runBuilderJob( KDevelop::BuilderJob::Clean, collectItems() ); } void ProjectManagerViewPlugin::buildProjectItems() { - runBuilderJob( KDevelop::BuilderJob::Build ); + runBuilderJob( KDevelop::BuilderJob::Build, collectItems() ); } void ProjectManagerViewPlugin::addItemsFromContextMenuToBuildset( ) { foreach( KDevelop::ProjectBaseItem* item, d->ctxProjectItemList ) { ICore::self()->projectController()->buildSetModel()->addProjectItem( item ); } } void ProjectManagerViewPlugin::runTargetsFromContextMenu( ) { foreach( KDevelop::ProjectBaseItem* item, d->ctxProjectItemList ) { KDevelop::ProjectExecutableTargetItem* t=item->executable(); if(t) { kDebug() << "Running target: " << t->text() << t->builtUrl(); } } } void ProjectManagerViewPlugin::projectConfiguration( ) { if( !d->ctxProjectItemList.isEmpty() ) { core()->projectController()->configureProject( d->ctxProjectItemList.at( 0 )->project() ); } } void ProjectManagerViewPlugin::reloadFromContextMenu( ) { QList< KDevelop::ProjectFolderItem* > folders; foreach( KDevelop::ProjectBaseItem* item, d->ctxProjectItemList ) { if ( item->folder() ) { // since reloading should be recursive, only pass the upper-most items bool found = false; foreach ( KDevelop::ProjectFolderItem* existing, folders ) { if ( existing->url().isParentOf(item->folder()->url()) ) { // simply skip this child found = true; break; } else if ( item->folder()->url().isParentOf(existing->url()) ) { // remove the child in the list and add the current item instead folders.removeOne(existing); // continue since there could be more than one existing child } } if ( !found ) { folders << item->folder(); } } } foreach( KDevelop::ProjectFolderItem* folder, folders ) { folder->project()->projectFileManager()->reload(folder); } } void ProjectManagerViewPlugin::createFolderFromContextMenu( ) { foreach( KDevelop::ProjectBaseItem* item, d->ctxProjectItemList ) { if ( item->folder() ) { QWidget* window(ICore::self()->uiController()->activeMainWindow()->window()); QString name = QInputDialog::getText ( window, i18n ( "Create Folder in %1", item->folder()->url().prettyUrl() ), i18n ( "Folder Name" ) ); if (!name.isEmpty()) { KUrl url = item->folder()->url(); url.addPath( name ); item->project()->projectFileManager()->addFolder( url, item->folder() ); } } } } void ProjectManagerViewPlugin::removeFromContextMenu() { removeItems(d->ctxProjectItemList); } void ProjectManagerViewPlugin::removeItems(const QList< ProjectBaseItem* >& items) { if (items.isEmpty()) { return; } //copy the list of selected items and sort it to guarantee parents will come before children QMap< IProjectFileManager*, QList > filteredItems; filteredItems[0] = items; qSort(filteredItems[0].begin(), filteredItems[0].end(), ProjectBaseItem::urlLessThan); KUrl lastFolder; QStringList itemPaths; foreach( KDevelop::ProjectBaseItem* item, filteredItems[0] ) { Q_ASSERT(item->folder() || item->file()); Q_ASSERT(!item->file() || !item->file()->parent()->target()); if (item->folder() || item->file()) { //make sure no children of folders that will be deleted are listed if (lastFolder.isParentOf(item->url())) { continue; } else if (item->folder()) { lastFolder = item->url(); } filteredItems[item->project()->projectFileManager()] << item; itemPaths << item->url().path(); } } if (KMessageBox::warningYesNoList( QApplication::activeWindow(), i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", itemPaths.size()), itemPaths, i18n("Delete Files"), KStandardGuiItem::del(), KStandardGuiItem::cancel() ) == KMessageBox::No) { return; } //Go though projectmanagers, have them remove the files and folders that they own QMap< IProjectFileManager*, QList >::iterator it; for (it = filteredItems.begin(); it != filteredItems.end(); ++it) { if (it.key()) it.key()->removeFilesAndFolders(it.value()); } } void ProjectManagerViewPlugin::removeTargetFilesFromContextMenu() { QList items = d->ctxProjectItemList; QMap< IBuildSystemManager*, QList > itemsByBuildSystem; foreach(ProjectBaseItem *item, items) itemsByBuildSystem[item->project()->buildSystemManager()].append(item->file()); QMap< IBuildSystemManager*, QList >::iterator it; for (it = itemsByBuildSystem.begin(); it != itemsByBuildSystem.end(); ++it) it.key()->removeFilesFromTargets(it.value()); } void ProjectManagerViewPlugin::renameItemFromContextMenu() { renameItems(d->ctxProjectItemList); } void ProjectManagerViewPlugin::renameItems(const QList< ProjectBaseItem* >& items) { if (items.isEmpty()) { return; } QWidget* window = ICore::self()->uiController()->activeMainWindow()->window(); foreach( KDevelop::ProjectBaseItem* item, items ) { if ((item->type()!=ProjectBaseItem::BuildFolder && item->type()!=ProjectBaseItem::Folder && item->type()!=ProjectBaseItem::File) || !item->parent()) { continue; } const QString src = item->text(); //Change QInputDialog->KFileSaveDialog? QString name = QInputDialog::getText( window, i18n("Rename..."), i18n("New name for '%1'", item->text()), QLineEdit::Normal, item->text() ); if (!name.isEmpty() && name != src) { ProjectBaseItem::RenameStatus status = item->rename( name ); switch(status) { case ProjectBaseItem::RenameOk: break; case ProjectBaseItem::ExistingItemSameName: KMessageBox::error(window, i18n("There is already a file named '%1'", name)); break; case ProjectBaseItem::ProjectManagerRenameFailed: KMessageBox::error(window, i18n("Could not rename '%1'", name)); break; case ProjectBaseItem::InvalidNewName: KMessageBox::error(window, i18n("'%1' is not a valid file name", name)); break; } } } } ProjectFileItem* createFile(const ProjectFolderItem* item) { QWidget* window = ICore::self()->uiController()->activeMainWindow()->window(); QString name = QInputDialog::getText(window, i18n("Create File in %1", item->url().prettyUrl()), i18n("File Name")); if(name.isEmpty()) return 0; KUrl url=item->url(); url.addPath( name ); ProjectFileItem* ret=item->project()->projectFileManager()->addFile( url, item->folder() ); ICore::self()->documentController()->openDocument( url ); return ret; } void ProjectManagerViewPlugin::createFileFromContextMenu( ) { foreach( KDevelop::ProjectBaseItem* item, d->ctxProjectItemList ) { if ( item->folder() ) { createFile(item->folder()); } else if ( item->target() ) { ProjectFolderItem* folder=dynamic_cast(item->parent()); if(folder) { ProjectFileItem* f=createFile(folder); if(f) item->project()->buildSystemManager()->addFilesToTarget(QList() << f, item->target()); } } } } #include "projectmanagerviewplugin.moc" diff --git a/plugins/projectmanagerview/projectmanagerviewplugin.h b/plugins/projectmanagerview/projectmanagerviewplugin.h index 6b15844825..5af3d82ef2 100644 --- a/plugins/projectmanagerview/projectmanagerviewplugin.h +++ b/plugins/projectmanagerview/projectmanagerviewplugin.h @@ -1,94 +1,96 @@ /* This file is part of KDevelop Copyright 2004 Roberto Raggi Copyright 2007 Andreas Pakulat This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPROJECTMANAGERVIEWPLUGIN_H #define KDEVPROJECTMANAGERVIEWPLUGIN_H #include #include #include #include class KUrl; class ProjectBuildSetModel; namespace KDevelop { class ProjectBaseItem; class ProjectBuilder; class ProjectFileItem; class ProjectFolderItem; class ProjectTargetItem; class IProjectBuilder; class IProject; class ContextMenuExtension; class Context; } class ProjectManagerView; class ProjectManagerViewPlugin: public KDevelop::IPlugin { Q_OBJECT public: public: ProjectManagerViewPlugin(QObject *parent, const QVariantList & = QVariantList() ); virtual ~ProjectManagerViewPlugin(); // Plugin methods virtual void unload(); KDevelop::ContextMenuExtension contextMenuExtension( KDevelop::Context* ); void removeItems(const QList& items); void renameItems(const QList< KDevelop::ProjectBaseItem* >& items); public Q_SLOTS: void buildProjectItems(); void installProjectItems(); void cleanProjectItems(); protected Q_SLOTS: void closeProjects(); void buildItemsFromContextMenu(); void installItemsFromContextMenu(); void cleanItemsFromContextMenu(); void configureProjectItems(); void pruneProjectItems(); void buildAllProjects(); void addItemsFromContextMenuToBuildset(); void projectConfiguration(); void runTargetsFromContextMenu(); void reloadFromContextMenu(); void createFolderFromContextMenu(); void createFileFromContextMenu(); void removeFromContextMenu(); void removeTargetFilesFromContextMenu(); void renameItemFromContextMenu(); void updateActionState( KDevelop::Context* ctx ); void updateFromBuildSetChange(); private: QList recurseAndFetchCheckedItems( KDevelop::ProjectBaseItem* item ); - void runBuilderJob( KDevelop::BuilderJob::BuildType ); + QList collectItems(); + QList collectAllProjects(); + void runBuilderJob( KDevelop::BuilderJob::BuildType type, QList items ); class ProjectManagerViewPluginPrivate* const d; }; #endif diff --git a/project/builderjob.cpp b/project/builderjob.cpp index 44519d3266..09f7fa782b 100644 --- a/project/builderjob.cpp +++ b/project/builderjob.cpp @@ -1,195 +1,290 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "builderjob.h" #include +#include #include #include #include #include #include #include #include #include #include namespace KDevelop { class BuilderJobPrivate { public: BuilderJobPrivate( BuilderJob* job ) { q = job; failOnFirstError = true; } BuilderJob* q; void addJob( BuilderJob::BuildType, KDevelop::ProjectBaseItem* ); bool failOnFirstError; }; void BuilderJobPrivate::addJob( BuilderJob::BuildType t, KDevelop::ProjectBaseItem* item ) { Q_ASSERT(item); kDebug() << "adding build job for item:" << item->text(); Q_ASSERT(item->project()); kDebug() << "project for item:" << item->project()->name(); Q_ASSERT(item->project()->projectItem()); kDebug() << "project item for the project:" << item->project()->projectItem()->text(); if( !item->project()->buildSystemManager() ) { kWarning() << "no buildsystem manager for:" << item->text() << item->project()->name(); return; } kDebug() << "got build system manager"; Q_ASSERT(item->project()->buildSystemManager()->builder()); KJob* j = 0; switch( t ) { case BuilderJob::Build: j = item->project()->buildSystemManager()->builder()->build( item ); break; case BuilderJob::Clean: j = item->project()->buildSystemManager()->builder()->clean( item ); break; case BuilderJob::Install: j = item->project()->buildSystemManager()->builder()->install( item ); break; case BuilderJob::Prune: j = item->project()->buildSystemManager()->builder()->prune( item->project() ); break; case BuilderJob::Configure: j = item->project()->buildSystemManager()->builder()->configure( item->project() ); break; default: break; } if( j ) { - q->addSubjob( j ); + q->addCustomJob( t, j, item ); } } BuilderJob::BuilderJob() : d( new BuilderJobPrivate( this ) ) { } void BuilderJob::addItems( BuildType t, const QList& items ) { foreach( KDevelop::ProjectBaseItem* item, items ) { d->addJob( t, item ); } } void BuilderJob::addProjects( BuildType t, const QList& projects ) { foreach( KDevelop::IProject* project, projects ) { d->addJob( t, project->projectItem() ); } } void BuilderJob::addItem( BuildType t, ProjectBaseItem* item ) { d->addJob( t, item ); } +void BuilderJob::addCustomJob( BuilderJob::BuildType type, KJob* job, ProjectBaseItem* item ) +{ + if( BuilderJob* builderJob = dynamic_cast( job ) ) { + // If a subjob is a builder job itself, re-own its job list to avoid having recursive composite jobs. + QVector< BuilderJob::SubJobData > subjobs = builderJob->takeJobList(); + builderJob->deleteLater(); + foreach( const BuilderJob::SubJobData& subjob, subjobs ) { + addSubjob( subjob.job ); + } + m_metadata << subjobs; + } else { + addSubjob( job ); + + SubJobData data; + data.type = type; + data.job = job; + data.item = item; + m_metadata << data; + } +} + +QVector< BuilderJob::SubJobData > BuilderJob::takeJobList() +{ + QVector< SubJobData > ret = m_metadata; + m_metadata.clear(); + clearSubjobs(); + setObjectName( QString() ); + return ret; +} + +void BuilderJob::updateJobName() +{ + // Which items are mentioned in the set + // Make it a list to preserve ordering; search overhead (n^2) isn't too big + QList< ProjectBaseItem* > registeredItems; + // Which build types are mentioned in the set + // (Same rationale applies) + QList< BuildType > buildTypes; + // Whether there are jobs without any specific item + bool hasNullItems = false; + + foreach( const SubJobData& subjob, m_metadata ) { + if( subjob.item ) { + if( !registeredItems.contains( subjob.item ) ) { + registeredItems.append( subjob.item ); + } + if( !buildTypes.contains( subjob.type ) ) { + buildTypes.append( subjob.type ); + } + } else { + hasNullItems = true; + } + } + + QString itemNames; + if( !hasNullItems ) { + QStringList itemNamesList; + foreach( ProjectBaseItem* item, registeredItems ) { + itemNamesList << item->text(); + } + itemNames = itemNamesList.join(", "); + } else { + itemNames = i18nc( "Unspecified set of build items (e. g. projects, targets)", "Various items" ); + } + + QString methodNames; + QStringList methodNamesList; + foreach( BuildType type, buildTypes ) { + methodNamesList << buildTypeToString( type ); + } + methodNames = methodNamesList.join( ", " ); + + QString jobName = QString( "%1: %2" ).arg( itemNames ).arg( methodNames ); + setObjectName( jobName ); +} + +QString BuilderJob::buildTypeToString( BuilderJob::BuildType type ) +{ + switch( type ) { + case Build: + return i18nc( "@info:status", "build" ); + case Clean: + return i18nc( "@info:status", "clean" ); + case Configure: + return i18nc( "@info:status", "configure" ); + case Install: + return i18nc( "@info:status", "install" ); + case Prune: + return i18nc( "@info:status", "prune" ); + default: + return QString(); + } +} + void BuilderJob::start() { #if 0 ///Running the same builder twice may result in serious problems, so kill jobs already running on the same project QList > jobs; foreach(KJob* job, KDevelop::ICore::self()->runController()->currentJobs()) { kDebug() << "running" << job; jobs << job; } for(QList< QPointer< KJob > >::iterator it = jobs.begin(); it != jobs.end(); ++it) { QPointer< KJob > job = *it; if(!job) continue; BuilderJob* bJob = dynamic_cast(job.data()); if( bJob && bJob != this ) { kDebug() << "killing running builder job, due to new started build"; //Copy the subjobs into QPointers first, as we never know what is deleted when QList > subJobs; foreach(KJob* subJob, bJob->subjobs()) subJobs << subJob; // while(!subJobs.empty()) { // if(subJobs.back() && subJobs.back()->capabilities() & KJob::Killable) // subJobs.back()->kill(EmitResult); // subJobs.pop_front(); // } if(job && job->capabilities() & KJob::Killable) job->kill(EmitResult); } } #endif // Automatically save all documents before starting to build // might need an option to turn off at some point // Also should be moved into the builder and there try to find target(s) for the given item and then just save the documents of that target -> list?? if( ICore::self()->activeSession()->config()->group("Project Manager").readEntry( "Save All Documents Before Building", true ) ) { KDevelop::ICore::self()->documentController()->saveAllDocuments( KDevelop::IDocument::Silent ); } if(hasSubjobs()) KDevelop::ICore::self()->runController()->registerJob( subjobs().first() ); else emitResult(); } void BuilderJob::slotResult( KJob* job ) { //call parent implementation for default behaviour KCompositeJob::slotResult( job ); if( ( !error() || !d->failOnFirstError ) && hasSubjobs() ) { // start next build; KDevelop::ICore::self()->runController()->registerJob( subjobs().first() ); } else { emitResult(); } } void BuilderJob::setStopOnFail( bool stopOnFail ) { d->failOnFirstError = stopOnFail; } bool BuilderJob::stopOnFail() const { return d->failOnFirstError; } } #include "builderjob.moc" diff --git a/project/builderjob.h b/project/builderjob.h index 297f18768d..04c7a1394e 100644 --- a/project/builderjob.h +++ b/project/builderjob.h @@ -1,121 +1,158 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef BUILDERJOB_H #define BUILDERJOB_H -#include +#include #include #include "projectexport.h" class KConfigGroup; namespace KDevelop { class ProjectBaseItem; class IProject; /** * Allows to build a list of project items or projects sequentially, where * failing to build one item in the list will fail the whole job. */ class KDEVPLATFORMPROJECT_EXPORT BuilderJob : public KCompositeJob { Q_OBJECT public: /** * Defines what action to do on the Project builder */ enum BuildType { Build /**< Build the selected items */, Prune /**< Prune the selected items */, Configure /**< Configure the selected items */, Install /**< Install the selected items */, Clean /**< Clean the selected items */ }; /** * Creates a Builder job */ BuilderJob(); /** * Allows to easily schedule building a couple of @p items using the * method identified by @p type * * @param type the build method to use * @param items the project items to add */ void addItems( BuildType type, const QList& items ); /** * Allows to easily schedule building a couple of @p projects using the * method identified by @p type * * @param type the build method to use * @param projects the projects to add */ void addProjects( BuildType type, const QList& projects ); /** * Allows to add a single @p item to the end of the list. The item will be * built using the method identified by @p type * * @param item The item to add to the list * @param type The build method to be used for the item */ void addItem( BuildType type, ProjectBaseItem* item ); - + + /** + * Allows to add a custom @p job to the end of the list. The build method specified by @p type + * and (optionally) an item specified by @p item are needed to create a human-readable job name. + * + * @param type The build method which is represented by the @p job + * @param job The job to add to the list + * @param item The item which is build by the @p job + */ + void addCustomJob( BuildType type, KJob* job, ProjectBaseItem* item = 0 ); + + /** + * Updates the job's name. + * + * Shall be called before registering this job in the run controller, but after + * adding all required tasks to the job. + */ + void updateJobName(); + /** * Allows to choose between stopping and failing the composite job * when the first item could not be built, or building all items * The default for this is true. * @param stopOnFail if set to true this job will stop and fail when the first * item in the list cannot be build */ void setStopOnFail( bool stopOnFail ); /** * Find out whether this builderjob stops building items on the first failed * item. * @returns true if this job stops and fails when the first subjob failed */ bool stopOnFail() const; /** * Starts this job */ void start(); protected Q_SLOTS: /** * @internal slot to handle the result from subjobs */ virtual void slotResult( KJob* ); private: class BuilderJobPrivate* const d; friend class BuilderJobPrivate; + + QString buildTypeToString( BuildType type ); + + /** + * @internal a structure to keep metadata of all registered jobs + */ + struct SubJobData + { + BuildType type; + KJob* job; + ProjectBaseItem* item; + }; + QVector m_metadata; + + /** + * @internal get the subjob list and clear this composite job + */ + QVector takeJobList(); + }; } #endif