1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** If you are unsure which license is appropriate for your use, please
26 ** contact the sales department at http://qt.nokia.com/contact.
28 **************************************************************************/
30 #include "projectexplorer.h"
33 #include "projectexplorersettings.h"
35 #include "targetsettingspanel.h"
36 #include "copytaskhandler.h"
37 #include "showineditortaskhandler.h"
38 #include "vcsannotatetaskhandler.h"
39 #include "applicationrunconfiguration.h"
40 #include "allprojectsfilter.h"
41 #include "allprojectsfind.h"
42 #include "buildmanager.h"
43 #include "buildsettingspropertiespage.h"
44 #include "currentprojectfind.h"
45 #include "currentprojectfilter.h"
46 #include "customexecutablerunconfiguration.h"
47 #include "editorsettingspropertiespage.h"
48 #include "dependenciespanel.h"
49 #include "foldernavigationwidget.h"
50 #include "iprojectmanager.h"
51 #include "metatypedeclarations.h"
52 #include "nodesvisitor.h"
53 #include "outputwindow.h"
54 #include "persistentsettings.h"
55 #include "pluginfilefactory.h"
56 #include "processstep.h"
57 #include "projectexplorerconstants.h"
58 #include "customwizard.h"
59 #include "projectfilewizardextension.h"
60 #include "projecttreewidget.h"
61 #include "projectwindow.h"
62 #include "removefiledialog.h"
63 #include "runsettingspropertiespage.h"
64 #include "scriptwrappers.h"
66 #include "sessiondialog.h"
68 #include "projectexplorersettingspage.h"
69 #include "projectwelcomepage.h"
70 #include "projectwelcomepagewidget.h"
71 #include "corelistenercheckingforrunningbuild.h"
72 #include "buildconfiguration.h"
73 #include "buildconfigdialog.h"
74 #include "miniprojecttargetselector.h"
76 #include <coreplugin/basemode.h>
77 #include <coreplugin/coreconstants.h>
78 #include <coreplugin/filemanager.h>
79 #include <coreplugin/icore.h>
80 #include <coreplugin/mainwindow.h>
81 #include <coreplugin/mimedatabase.h>
82 #include <coreplugin/modemanager.h>
83 #include <coreplugin/actionmanager/actionmanager.h>
84 #include <coreplugin/actionmanager/actioncontainer.h>
85 #include <coreplugin/actionmanager/command.h>
86 #include <coreplugin/editormanager/editormanager.h>
87 #include <coreplugin/editormanager/ieditor.h>
88 #include <coreplugin/editormanager/ieditorfactory.h>
89 #include <coreplugin/editormanager/iexternaleditor.h>
90 #include <coreplugin/findplaceholder.h>
91 #include <coreplugin/basefilewizard.h>
92 #include <coreplugin/vcsmanager.h>
93 #include <coreplugin/iversioncontrol.h>
94 #include <welcome/welcomemode.h>
95 #include <extensionsystem/pluginmanager.h>
96 #include <utils/consoleprocess.h>
97 #include <utils/qtcassert.h>
98 #include <utils/parameteraction.h>
100 #include <QtCore/QtPlugin>
101 #include <QtCore/QDateTime>
102 #include <QtCore/QDebug>
103 #include <QtCore/QSettings>
105 #include <QtGui/QAction>
106 #include <QtGui/QApplication>
107 #include <QtGui/QFileDialog>
108 #include <QtGui/QMenu>
109 #include <QtGui/QMessageBox>
111 Q_DECLARE_METATYPE(Core::IEditorFactory*);
112 Q_DECLARE_METATYPE(Core::IExternalEditor*);
118 namespace ProjectExplorer {
120 struct ProjectExplorerPluginPrivate {
121 ProjectExplorerPluginPrivate();
123 QMenu *m_sessionContextMenu;
124 QMenu *m_sessionMenu;
125 QMenu *m_projectMenu;
126 QMenu *m_subProjectMenu;
129 QMenu *m_openWithMenu;
131 QMultiMap<int, QObject*> m_actionMap;
132 QAction *m_sessionManagerAction;
133 QAction *m_newAction;
135 QAction *m_loadAction;
137 Utils::ParameterAction *m_unloadAction;
138 QAction *m_clearSession;
139 QAction *m_buildProjectOnlyAction;
140 Utils::ParameterAction *m_buildAction;
141 Utils::ParameterAction *m_buildActionContextMenu;
142 QAction *m_buildSessionAction;
143 QAction *m_rebuildProjectOnlyAction;
144 Utils::ParameterAction *m_rebuildAction;
145 Utils::ParameterAction *m_rebuildActionContextMenu;
146 QAction *m_rebuildSessionAction;
147 QAction *m_cleanProjectOnlyAction;
148 Utils::ParameterAction *m_cleanAction;
149 Utils::ParameterAction *m_cleanActionContextMenu;
150 QAction *m_cleanSessionAction;
151 QAction *m_runAction;
152 QAction *m_runActionContextMenu;
153 QAction *m_cancelBuildAction;
154 QAction *m_debugAction;
155 QAction *m_addNewFileAction;
156 QAction *m_addExistingFilesAction;
157 QAction *m_openFileAction;
158 QAction *m_showInGraphicalShell;
159 QAction *m_openTerminalHere;
160 QAction *m_removeFileAction;
161 QAction *m_renameFileAction;
162 QAction *m_projectSelectorAction;
163 QAction *m_projectSelectorActionMenu;
165 Internal::ProjectWindow *m_proWindow;
166 SessionManager *m_session;
167 QString m_sessionToRestoreAtStartup;
169 Project *m_currentProject;
172 BuildManager *m_buildManager;
174 QList<Internal::ProjectFileFactory*> m_fileFactories;
175 QStringList m_profileMimeTypes;
176 Internal::OutputPane *m_outputPane;
178 QList<QPair<QString, QString> > m_recentProjects; // pair of filename, displayname
179 static const int m_maxRecentProjects = 7;
181 QString m_lastOpenDirectory;
182 RunConfiguration *m_delayedRunConfiguration; // TODO this is not right
183 RunControl *m_debuggingRunControl;
185 QString m_projectFilterString;
186 Internal::MiniProjectTargetSelector * m_targetSelector;
187 Internal::ProjectExplorerSettings m_projectExplorerSettings;
188 Internal::ProjectWelcomePage *m_welcomePage;
190 Core::BaseMode * m_projectsMode;
193 ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() :
196 m_delayedRunConfiguration(0),
197 m_debuggingRunControl(0),
202 } // namespace ProjectExplorer
204 using namespace ProjectExplorer;
205 using namespace ProjectExplorer::Internal;
208 ProjectExplorerPlugin *ProjectExplorerPlugin::m_instance = 0;
210 ProjectExplorerPlugin::ProjectExplorerPlugin()
211 : d(new ProjectExplorerPluginPrivate)
216 ProjectExplorerPlugin::~ProjectExplorerPlugin()
218 removeObject(d->m_welcomePage);
219 delete d->m_welcomePage;
224 ProjectExplorerPlugin *ProjectExplorerPlugin::instance()
229 bool ProjectExplorerPlugin::parseArguments(const QStringList &arguments, QString * /* error */)
231 CustomWizard::setVerbose(arguments.count(QLatin1String("-customwizard-verbose")));
235 bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *error)
237 if (!parseArguments(arguments, error))
240 Core::ICore *core = Core::ICore::instance();
241 Core::ActionManager *am = core->actionManager();
243 d->m_welcomePage = new ProjectWelcomePage;
244 connect(d->m_welcomePage, SIGNAL(manageSessions()), this, SLOT(showSessionManager()));
245 addObject(d->m_welcomePage);
248 connect(core->fileManager(), SIGNAL(currentFileChanged(QString)),
249 this, SLOT(setCurrentFile(QString)));
251 d->m_session = new SessionManager(this);
253 connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project *)),
254 this, SIGNAL(fileListChanged()));
255 connect(d->m_session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project *)),
256 this, SLOT(invalidateProject(ProjectExplorer::Project *)));
257 connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project *)),
258 this, SIGNAL(fileListChanged()));
259 connect(d->m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project *)),
260 this, SLOT(startupProjectChanged()));
261 connect(d->m_session, SIGNAL(dependencyChanged(ProjectExplorer::Project*,ProjectExplorer::Project*)),
262 this, SLOT(updateActions()));
264 d->m_proWindow = new ProjectWindow;
266 Core::Context globalcontext(Core::Constants::C_GLOBAL);
267 Core::Context pecontext(Constants::C_PROJECTEXPLORER);
269 d->m_projectsMode = new Core::BaseMode;
270 d->m_projectsMode->setDisplayName(tr("Projects"));
271 d->m_projectsMode->setId(QLatin1String(Constants::MODE_SESSION));
272 d->m_projectsMode->setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Project.png")));
273 d->m_projectsMode->setPriority(Constants::P_MODE_SESSION);
274 d->m_projectsMode->setWidget(d->m_proWindow);
275 d->m_projectsMode->setContext(pecontext);
276 d->m_projectsMode->setEnabled(session()->startupProject());
277 d->m_projectsMode->setContextHelpId(QLatin1String("Managing Projects"));
278 addAutoReleasedObject(d->m_projectsMode);
279 d->m_proWindow->layout()->addWidget(new Core::FindToolBarPlaceHolder(d->m_proWindow));
281 addAutoReleasedObject(new CopyTaskHandler);
282 addAutoReleasedObject(new ShowInEditorTaskHandler);
283 addAutoReleasedObject(new VcsAnnotateTaskHandler);
285 d->m_buildManager = new BuildManager(this);
286 connect(d->m_buildManager, SIGNAL(buildStateChanged(ProjectExplorer::Project *)),
287 this, SLOT(buildStateChanged(ProjectExplorer::Project *)));
288 connect(d->m_buildManager, SIGNAL(buildQueueFinished(bool)),
289 this, SLOT(buildQueueFinished(bool)));
291 addAutoReleasedObject(new CoreListenerCheckingForRunningBuild(d->m_buildManager));
293 d->m_outputPane = new OutputPane;
294 addAutoReleasedObject(d->m_outputPane);
295 connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project *)),
296 d->m_outputPane, SLOT(projectRemoved()));
298 AllProjectsFilter *allProjectsFilter = new AllProjectsFilter(this);
299 addAutoReleasedObject(allProjectsFilter);
301 CurrentProjectFilter *currentProjectFilter = new CurrentProjectFilter(this);
302 addAutoReleasedObject(currentProjectFilter);
304 addAutoReleasedObject(new BuildSettingsPanelFactory);
305 addAutoReleasedObject(new RunSettingsPanelFactory);
306 addAutoReleasedObject(new EditorSettingsPanelFactory);
307 addAutoReleasedObject(new DependenciesPanelFactory(d->m_session));
309 ProcessStepFactory *processStepFactory = new ProcessStepFactory;
310 addAutoReleasedObject(processStepFactory);
312 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
313 AllProjectsFind *allProjectsFind = new AllProjectsFind(this,
314 pm->getObject<Find::SearchResultWindow>());
315 addAutoReleasedObject(allProjectsFind);
317 CurrentProjectFind *currentProjectFind = new CurrentProjectFind(this,
318 pm->getObject<Find::SearchResultWindow>());
319 addAutoReleasedObject(currentProjectFind);
321 addAutoReleasedObject(new LocalApplicationRunControlFactory);
322 addAutoReleasedObject(new CustomExecutableRunConfigurationFactory);
324 addAutoReleasedObject(new ProjectFileWizardExtension);
327 addAutoReleasedObject(new ProjectExplorerSettingsPage);
330 Core::ActionContainer *msessionContextMenu =
331 am->createMenu(Constants::M_SESSIONCONTEXT);
332 Core::ActionContainer *mproject =
333 am->createMenu(Constants::M_PROJECTCONTEXT);
334 Core::ActionContainer *msubProject =
335 am->createMenu(Constants::M_SUBPROJECTCONTEXT);
336 Core::ActionContainer *mfolder =
337 am->createMenu(Constants::M_FOLDERCONTEXT);
338 Core::ActionContainer *mfilec =
339 am->createMenu(Constants::M_FILECONTEXT);
341 d->m_sessionContextMenu = msessionContextMenu->menu();
342 d->m_projectMenu = mproject->menu();
343 d->m_subProjectMenu = msubProject->menu();
344 d->m_folderMenu = mfolder->menu();
345 d->m_fileMenu = mfilec->menu();
347 Core::ActionContainer *mfile =
348 am->actionContainer(Core::Constants::M_FILE);
349 Core::ActionContainer *menubar =
350 am->actionContainer(Core::Constants::MENU_BAR);
352 // mode manager (for fancy actions)
353 Core::ModeManager *modeManager = core->modeManager();
356 Core::ActionContainer *mbuild =
357 am->createMenu(Constants::M_BUILDPROJECT);
358 mbuild->menu()->setTitle(tr("&Build"));
359 menubar->addMenu(mbuild, Core::Constants::G_VIEW);
362 Core::ActionContainer *mdebug =
363 am->createMenu(Constants::M_DEBUG);
364 mdebug->menu()->setTitle(tr("&Debug"));
365 menubar->addMenu(mdebug, Core::Constants::G_VIEW);
367 Core::ActionContainer *mstartdebugging =
368 am->createMenu(Constants::M_DEBUG_STARTDEBUGGING);
369 mstartdebugging->menu()->setTitle(tr("&Start Debugging"));
370 mdebug->addMenu(mstartdebugging, Core::Constants::G_DEFAULT_ONE);
376 mbuild->appendGroup(Constants::G_BUILD_SESSION);
377 mbuild->appendGroup(Constants::G_BUILD_PROJECT);
378 mbuild->appendGroup(Constants::G_BUILD_OTHER);
379 mbuild->appendGroup(Constants::G_BUILD_CANCEL);
380 mbuild->appendGroup(Constants::G_BUILD_RUN);
382 msessionContextMenu->appendGroup(Constants::G_SESSION_BUILD);
383 msessionContextMenu->appendGroup(Constants::G_SESSION_FILES);
384 msessionContextMenu->appendGroup(Constants::G_SESSION_OTHER);
385 msessionContextMenu->appendGroup(Constants::G_SESSION_CONFIG);
387 mproject->appendGroup(Constants::G_PROJECT_OPEN);
388 mproject->appendGroup(Constants::G_PROJECT_NEW);
389 mproject->appendGroup(Constants::G_PROJECT_BUILD);
390 mproject->appendGroup(Constants::G_PROJECT_RUN);
391 mproject->appendGroup(Constants::G_PROJECT_FILES);
392 mproject->appendGroup(Constants::G_PROJECT_OTHER);
393 mproject->appendGroup(Constants::G_PROJECT_CONFIG);
395 msubProject->appendGroup(Constants::G_PROJECT_OPEN);
396 msubProject->appendGroup(Constants::G_PROJECT_BUILD);
397 msubProject->appendGroup(Constants::G_PROJECT_FILES);
398 msubProject->appendGroup(Constants::G_PROJECT_OTHER);
399 msubProject->appendGroup(Constants::G_PROJECT_CONFIG);
401 mfolder->appendGroup(Constants::G_FOLDER_FILES);
402 mfolder->appendGroup(Constants::G_FOLDER_OTHER);
403 mfolder->appendGroup(Constants::G_FOLDER_CONFIG);
405 mfilec->appendGroup(Constants::G_FILE_OPEN);
406 mfilec->appendGroup(Constants::G_FILE_OTHER);
407 mfilec->appendGroup(Constants::G_FILE_CONFIG);
409 // "open with" submenu
410 Core::ActionContainer * const openWith =
411 am->createMenu(ProjectExplorer::Constants::M_OPENFILEWITHCONTEXT);
412 openWith->setEmptyAction(Core::ActionContainer::EA_None);
413 d->m_openWithMenu = openWith->menu();
414 d->m_openWithMenu->setTitle(tr("Open With"));
416 connect(d->m_openWithMenu, SIGNAL(triggered(QAction *)),
417 this, SLOT(openWithMenuTriggered(QAction *)));
426 sep = new QAction(this);
427 sep->setSeparator(true);
428 cmd = am->registerAction(sep, QLatin1String("ProjectExplorer.Build.Sep"), globalcontext);
429 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
431 sep = new QAction(this);
432 sep->setSeparator(true);
433 cmd = am->registerAction(sep, QLatin1String("ProjectExplorer.Files.Sep"), globalcontext);
434 msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
435 mproject->addAction(cmd, Constants::G_PROJECT_FILES);
436 msubProject->addAction(cmd, Constants::G_PROJECT_FILES);
438 sep = new QAction(this);
439 sep->setSeparator(true);
440 cmd = am->registerAction(sep, QLatin1String("ProjectExplorer.New.Sep"), globalcontext);
441 mproject->addAction(cmd, Constants::G_PROJECT_NEW);
443 sep = new QAction(this);
444 sep->setSeparator(true);
445 cmd = am->registerAction(sep, QLatin1String("ProjectExplorer.Config.Sep"), globalcontext);
446 msessionContextMenu->addAction(cmd, Constants::G_SESSION_CONFIG);
447 mproject->addAction(cmd, Constants::G_PROJECT_CONFIG);
448 msubProject->addAction(cmd, Constants::G_PROJECT_CONFIG);
450 sep = new QAction(this);
451 sep->setSeparator(true);
452 cmd = am->registerAction(sep, QLatin1String("ProjectExplorer.Projects.Sep"), globalcontext);
453 mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
455 sep = new QAction(this);
456 sep->setSeparator(true);
457 cmd = am->registerAction(sep, QLatin1String("ProjectExplorer.Other.Sep"), globalcontext);
458 mbuild->addAction(cmd, Constants::G_BUILD_OTHER);
459 msessionContextMenu->addAction(cmd, Constants::G_SESSION_OTHER);
460 mproject->addAction(cmd, Constants::G_PROJECT_OTHER);
461 msubProject->addAction(cmd, Constants::G_PROJECT_OTHER);
463 sep = new QAction(this);
464 sep->setSeparator(true);
465 cmd = am->registerAction(sep, QLatin1String("ProjectExplorer.Run.Sep"), globalcontext);
466 mbuild->addAction(cmd, Constants::G_BUILD_RUN);
467 mproject->addAction(cmd, Constants::G_PROJECT_RUN);
469 sep = new QAction(this);
470 sep->setSeparator(true);
471 cmd = am->registerAction(sep, QLatin1String("ProjectExplorer.CancelBuild.Sep"), globalcontext);
472 mbuild->addAction(cmd, Constants::G_BUILD_CANCEL);
478 // new session action
479 d->m_sessionManagerAction = new QAction(tr("Session Manager..."), this);
480 cmd = am->registerAction(d->m_sessionManagerAction, Constants::NEWSESSION, globalcontext);
481 cmd->setDefaultKeySequence(QKeySequence());
484 d->m_newAction = new QAction(tr("New Project..."), this);
485 cmd = am->registerAction(d->m_newAction, Constants::NEWPROJECT, globalcontext);
486 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+N")));
487 msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
491 d->m_loadAction = new QAction(tr("Load Project..."), this);
492 cmd = am->registerAction(d->m_loadAction, Constants::LOAD, globalcontext);
493 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+O")));
494 mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
495 msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
498 // Default open action
499 d->m_openFileAction = new QAction(tr("Open File"), this);
500 cmd = am->registerAction(d->m_openFileAction, ProjectExplorer::Constants::OPENFILE,
502 mfilec->addAction(cmd, Constants::G_FILE_OPEN);
504 d->m_showInGraphicalShell = new QAction(FolderNavigationWidget::msgGraphicalShellAction(), this);
505 cmd = am->registerAction(d->m_showInGraphicalShell, ProjectExplorer::Constants::SHOWINGRAPHICALSHELL,
507 mfilec->addAction(cmd, Constants::G_FILE_OPEN);
508 mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
510 d->m_openTerminalHere = new QAction(FolderNavigationWidget::msgTerminalAction(), this);
511 cmd = am->registerAction(d->m_openTerminalHere, ProjectExplorer::Constants::OPENTERMIANLHERE,
513 mfilec->addAction(cmd, Constants::G_FILE_OPEN);
514 mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
517 mfilec->addMenu(openWith, ProjectExplorer::Constants::G_FILE_OPEN);
519 // recent projects menu
520 Core::ActionContainer *mrecent =
521 am->createMenu(Constants::M_RECENTPROJECTS);
522 mrecent->menu()->setTitle(tr("Recent P&rojects"));
523 mfile->addMenu(mrecent, Core::Constants::G_FILE_OPEN);
524 connect(mfile->menu(), SIGNAL(aboutToShow()),
525 this, SLOT(updateRecentProjectMenu()));
528 d->m_unloadAction = new Utils::ParameterAction(tr("Close Project"), tr("Close Project \"%1\""),
529 Utils::ParameterAction::EnabledWithParameter, this);
530 cmd = am->registerAction(d->m_unloadAction, Constants::UNLOAD, globalcontext);
531 cmd->setAttribute(Core::Command::CA_UpdateText);
532 cmd->setDefaultText(d->m_unloadAction->text());
533 mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
534 mproject->addAction(cmd, Constants::G_PROJECT_FILES);
536 // unload session action
537 d->m_clearSession = new QAction(tr("Close All Projects"), this);
538 cmd = am->registerAction(d->m_clearSession, Constants::CLEARSESSION, globalcontext);
539 mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
540 msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
543 Core::ActionContainer *msession = am->createMenu(Constants::M_SESSION);
544 msession->menu()->setTitle(tr("Session"));
545 mfile->addMenu(msession, Core::Constants::G_FILE_PROJECT);
546 d->m_sessionMenu = msession->menu();
547 connect(mfile->menu(), SIGNAL(aboutToShow()),
548 this, SLOT(updateSessionMenu()));
550 // build session action
551 QIcon buildIcon(Constants::ICON_BUILD);
552 buildIcon.addFile(Constants::ICON_BUILD_SMALL);
553 d->m_buildSessionAction = new QAction(buildIcon, tr("Build All"), this);
554 cmd = am->registerAction(d->m_buildSessionAction, Constants::BUILDSESSION, globalcontext);
555 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+B")));
556 mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
557 msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
559 modeManager->addAction(cmd, Constants::P_ACTION_BUILDSESSION);
561 // rebuild session action
562 QIcon rebuildIcon(Constants::ICON_REBUILD);
563 rebuildIcon.addFile(Constants::ICON_REBUILD_SMALL);
564 d->m_rebuildSessionAction = new QAction(rebuildIcon, tr("Rebuild All"), this);
565 cmd = am->registerAction(d->m_rebuildSessionAction, Constants::REBUILDSESSION, globalcontext);
566 mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
567 msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
570 QIcon cleanIcon(Constants::ICON_CLEAN);
571 cleanIcon.addFile(Constants::ICON_CLEAN_SMALL);
572 d->m_cleanSessionAction = new QAction(cleanIcon, tr("Clean All"), this);
573 cmd = am->registerAction(d->m_cleanSessionAction, Constants::CLEANSESSION, globalcontext);
574 mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
575 msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
578 d->m_buildAction = new Utils::ParameterAction(tr("Build Project"), tr("Build Project \"%1\""),
579 Utils::ParameterAction::AlwaysEnabled, this);
580 cmd = am->registerAction(d->m_buildAction, Constants::BUILD, globalcontext);
581 cmd->setAttribute(Core::Command::CA_UpdateText);
582 cmd->setDefaultText(d->m_buildAction->text());
583 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+B")));
584 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
587 d->m_rebuildAction = new Utils::ParameterAction(tr("Rebuild Project"), tr("Rebuild Project \"%1\""),
588 Utils::ParameterAction::AlwaysEnabled, this);
589 cmd = am->registerAction(d->m_rebuildAction, Constants::REBUILD, globalcontext);
590 cmd->setAttribute(Core::Command::CA_UpdateText);
591 cmd->setDefaultText(d->m_rebuildAction->text());
592 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
595 d->m_cleanAction = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""),
596 Utils::ParameterAction::AlwaysEnabled, this);
597 cmd = am->registerAction(d->m_cleanAction, Constants::CLEAN, globalcontext);
598 cmd->setAttribute(Core::Command::CA_UpdateText);
599 cmd->setDefaultText(d->m_cleanAction->text());
600 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
602 // build action (context menu)
603 d->m_buildActionContextMenu = new Utils::ParameterAction(tr("Build Project"), tr("Build Project \"%1\""),
604 Utils::ParameterAction::AlwaysEnabled, this);
605 cmd = am->registerAction(d->m_buildActionContextMenu, Constants::BUILDCM, globalcontext);
606 cmd->setAttribute(Core::Command::CA_UpdateText);
607 cmd->setDefaultText(d->m_buildActionContextMenu->text());
608 mproject->addAction(cmd, Constants::G_PROJECT_BUILD);
610 // rebuild action (context menu)
611 d->m_rebuildActionContextMenu = new Utils::ParameterAction(tr("Rebuild Project"), tr("Rebuild Project \"%1\""),
612 Utils::ParameterAction::AlwaysEnabled, this);
613 cmd = am->registerAction(d->m_rebuildActionContextMenu, Constants::REBUILDCM, globalcontext);
614 cmd->setAttribute(Core::Command::CA_UpdateText);
615 cmd->setDefaultText(d->m_rebuildActionContextMenu->text());
616 mproject->addAction(cmd, Constants::G_PROJECT_BUILD);
618 // clean action (context menu)
619 d->m_cleanActionContextMenu = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""),
620 Utils::ParameterAction::AlwaysEnabled, this);
621 cmd = am->registerAction(d->m_cleanActionContextMenu, Constants::CLEANCM, globalcontext);
622 cmd->setAttribute(Core::Command::CA_UpdateText);
623 cmd->setDefaultText(d->m_cleanActionContextMenu->text());
624 mproject->addAction(cmd, Constants::G_PROJECT_BUILD);
626 // build without dependencies action
627 d->m_buildProjectOnlyAction = new QAction(tr("Build Without Dependencies"), this);
628 cmd = am->registerAction(d->m_buildProjectOnlyAction, Constants::BUILDPROJECTONLY, globalcontext);
630 // rebuild without dependencies action
631 d->m_rebuildProjectOnlyAction = new QAction(tr("Rebuild Without Dependencies"), this);
632 cmd = am->registerAction(d->m_rebuildProjectOnlyAction, Constants::REBUILDPROJECTONLY, globalcontext);
634 // clean without dependencies action
635 d->m_cleanProjectOnlyAction = new QAction(tr("Clean Without Dependencies"), this);
636 cmd = am->registerAction(d->m_cleanProjectOnlyAction, Constants::CLEANPROJECTONLY, globalcontext);
639 QIcon runIcon(Constants::ICON_RUN);
640 runIcon.addFile(Constants::ICON_RUN_SMALL);
641 d->m_runAction = new QAction(runIcon, tr("Run"), this);
642 cmd = am->registerAction(d->m_runAction, Constants::RUN, globalcontext);
643 cmd->setAttribute(Core::Command::CA_UpdateText);
645 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+R")));
646 mbuild->addAction(cmd, Constants::G_BUILD_RUN);
648 modeManager->addAction(cmd, Constants::P_ACTION_RUN);
650 d->m_runActionContextMenu = new QAction(runIcon, tr("Run"), this);
651 cmd = am->registerAction(d->m_runActionContextMenu, Constants::RUNCONTEXTMENU, globalcontext);
652 mproject->addAction(cmd, Constants::G_PROJECT_RUN);
654 // cancel build action
655 d->m_cancelBuildAction = new QAction(tr("Cancel Build"), this);
656 cmd = am->registerAction(d->m_cancelBuildAction, Constants::CANCELBUILD, globalcontext);
657 mbuild->addAction(cmd, Constants::G_BUILD_CANCEL);
660 QIcon debuggerIcon(":/projectexplorer/images/debugger_start_small.png");
661 debuggerIcon.addFile(":/projectexplorer/images/debugger_start.png");
662 d->m_debugAction = new QAction(debuggerIcon, tr("Start Debugging"), this);
663 cmd = am->registerAction(d->m_debugAction, Constants::DEBUG, globalcontext);
664 cmd->setAttribute(Core::Command::CA_UpdateText);
665 cmd->setAttribute(Core::Command::CA_UpdateIcon);
666 cmd->setDefaultText(tr("Start Debugging"));
667 cmd->setDefaultKeySequence(QKeySequence(tr("F5")));
668 mstartdebugging->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
669 modeManager->addAction(cmd, Constants::P_ACTION_DEBUG);
671 // add new file action
672 d->m_addNewFileAction = new QAction(tr("Add New..."), this);
673 cmd = am->registerAction(d->m_addNewFileAction, ProjectExplorer::Constants::ADDNEWFILE,
675 mproject->addAction(cmd, Constants::G_PROJECT_FILES);
676 msubProject->addAction(cmd, Constants::G_PROJECT_FILES);
677 mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
679 // add existing file action
680 d->m_addExistingFilesAction = new QAction(tr("Add Existing Files..."), this);
681 cmd = am->registerAction(d->m_addExistingFilesAction, ProjectExplorer::Constants::ADDEXISTINGFILES,
683 mproject->addAction(cmd, Constants::G_PROJECT_FILES);
684 msubProject->addAction(cmd, Constants::G_PROJECT_FILES);
685 mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
687 // remove file action
688 d->m_removeFileAction = new QAction(tr("Remove File..."), this);
689 cmd = am->registerAction(d->m_removeFileAction, ProjectExplorer::Constants::REMOVEFILE,
691 mfilec->addAction(cmd, Constants::G_FILE_OTHER);
694 d->m_renameFileAction = new QAction(tr("Rename"), this);
695 cmd = am->registerAction(d->m_renameFileAction, ProjectExplorer::Constants::RENAMEFILE,
697 mfilec->addAction(cmd, Constants::G_FILE_OTHER);
698 // Not yet used by anyone, so hide for now
699 // mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
700 // msubProject->addAction(cmd, Constants::G_FOLDER_FILES);
701 // mproject->addAction(cmd, Constants::G_FOLDER_FILES);
704 d->m_projectSelectorAction = new QAction(this);
705 d->m_projectSelectorAction->setCheckable(true);
706 d->m_projectSelectorAction->setEnabled(false);
707 QWidget *mainWindow = Core::ICore::instance()->mainWindow();
708 d->m_targetSelector = new Internal::MiniProjectTargetSelector(d->m_projectSelectorAction, mainWindow);
709 connect(d->m_projectSelectorAction, SIGNAL(triggered()), d->m_targetSelector, SLOT(show()));
710 modeManager->addProjectSelector(d->m_projectSelectorAction);
712 d->m_projectSelectorActionMenu = new QAction(this);
713 d->m_projectSelectorActionMenu->setEnabled(false);
714 d->m_projectSelectorActionMenu->setText(tr("Open Build/Run Target Selector..."));
715 connect(d->m_projectSelectorActionMenu, SIGNAL(triggered()), d->m_targetSelector, SLOT(show()));
716 cmd = am->registerAction(d->m_projectSelectorActionMenu, ProjectExplorer::Constants::SELECTTARGET,
718 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+T")));
719 mbuild->addAction(cmd, Constants::G_BUILD_RUN);
721 connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
722 d->m_targetSelector, SLOT(addProject(ProjectExplorer::Project*)));
723 connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)),
724 d->m_targetSelector, SLOT(removeProject(ProjectExplorer::Project*)));
725 connect(d->m_targetSelector, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
726 this, SLOT(setStartupProject(ProjectExplorer::Project*)));
727 connect(d->m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
728 d->m_targetSelector, SLOT(changeStartupProject(ProjectExplorer::Project*)));
730 connect(core, SIGNAL(saveSettingsRequested()),
731 this, SLOT(savePersistentSettings()));
733 addAutoReleasedObject(new ProjectTreeWidgetFactory);
734 addAutoReleasedObject(new FolderNavigationWidgetFactory);
736 if (QSettings *s = core->settings()) {
737 const QStringList fileNames = s->value("ProjectExplorer/RecentProjects/FileNames").toStringList();
738 const QStringList displayNames = s->value("ProjectExplorer/RecentProjects/DisplayNames").toStringList();
739 if (fileNames.size() == displayNames.size()) {
740 for (int i = 0; i < fileNames.size(); ++i) {
741 if (QFileInfo(fileNames.at(i)).isFile())
742 d->m_recentProjects.append(qMakePair(fileNames.at(i), displayNames.at(i)));
747 if (QSettings *s = core->settings()) {
748 d->m_projectExplorerSettings.buildBeforeRun = s->value("ProjectExplorer/Settings/BuildBeforeRun", true).toBool();
749 d->m_projectExplorerSettings.saveBeforeBuild = s->value("ProjectExplorer/Settings/SaveBeforeBuild", false).toBool();
750 d->m_projectExplorerSettings.showCompilerOutput = s->value("ProjectExplorer/Settings/ShowCompilerOutput", false).toBool();
751 d->m_projectExplorerSettings.cleanOldAppOutput = s->value("ProjectExplorer/Settings/CleanOldAppOutput", false).toBool();
752 d->m_projectExplorerSettings.useJom = s->value("ProjectExplorer/Settings/UseJom", true).toBool();
755 connect(d->m_sessionManagerAction, SIGNAL(triggered()), this, SLOT(showSessionManager()));
756 connect(d->m_newAction, SIGNAL(triggered()), this, SLOT(newProject()));
758 connect(d->m_loadAction, SIGNAL(triggered()), this, SLOT(loadAction()));
760 connect(d->m_buildProjectOnlyAction, SIGNAL(triggered()), this, SLOT(buildProjectOnly()));
761 connect(d->m_buildAction, SIGNAL(triggered()), this, SLOT(buildProject()));
762 connect(d->m_buildActionContextMenu, SIGNAL(triggered()), this, SLOT(buildProjectContextMenu()));
763 connect(d->m_buildSessionAction, SIGNAL(triggered()), this, SLOT(buildSession()));
764 connect(d->m_rebuildProjectOnlyAction, SIGNAL(triggered()), this, SLOT(rebuildProjectOnly()));
765 connect(d->m_rebuildAction, SIGNAL(triggered()), this, SLOT(rebuildProject()));
766 connect(d->m_rebuildActionContextMenu, SIGNAL(triggered()), this, SLOT(rebuildProjectContextMenu()));
767 connect(d->m_rebuildSessionAction, SIGNAL(triggered()), this, SLOT(rebuildSession()));
768 connect(d->m_cleanProjectOnlyAction, SIGNAL(triggered()), this, SLOT(cleanProjectOnly()));
769 connect(d->m_cleanAction, SIGNAL(triggered()), this, SLOT(cleanProject()));
770 connect(d->m_cleanActionContextMenu, SIGNAL(triggered()), this, SLOT(cleanProjectContextMenu()));
771 connect(d->m_cleanSessionAction, SIGNAL(triggered()), this, SLOT(cleanSession()));
772 connect(d->m_runAction, SIGNAL(triggered()), this, SLOT(runProject()));
773 connect(d->m_runActionContextMenu, SIGNAL(triggered()), this, SLOT(runProjectContextMenu()));
774 connect(d->m_cancelBuildAction, SIGNAL(triggered()), this, SLOT(cancelBuild()));
775 connect(d->m_debugAction, SIGNAL(triggered()), this, SLOT(debugProject()));
776 connect(d->m_unloadAction, SIGNAL(triggered()), this, SLOT(unloadProject()));
777 connect(d->m_clearSession, SIGNAL(triggered()), this, SLOT(clearSession()));
778 connect(d->m_addNewFileAction, SIGNAL(triggered()), this, SLOT(addNewFile()));
779 connect(d->m_addExistingFilesAction, SIGNAL(triggered()), this, SLOT(addExistingFiles()));
780 connect(d->m_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
781 connect(d->m_showInGraphicalShell, SIGNAL(triggered()), this, SLOT(showInGraphicalShell()));
782 connect(d->m_openTerminalHere, SIGNAL(triggered()), this, SLOT(openTerminalHere()));
783 connect(d->m_removeFileAction, SIGNAL(triggered()), this, SLOT(removeFile()));
784 connect(d->m_renameFileAction, SIGNAL(triggered()), this, SLOT(renameFile()));
788 connect(Core::ICore::instance(), SIGNAL(coreAboutToOpen()),
789 this, SLOT(determineSessionToRestoreAtStartup()));
790 connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(restoreSession()));
797 // Find a factory by file mime type in a sequence of factories
798 template <class Factory, class Iterator>
799 Factory *findFactory(const QString &mimeType, Iterator i1, Iterator i2)
801 for ( ; i1 != i2; ++i2) {
803 if (f->mimeTypes().contains(mimeType))
809 ProjectFileFactory * ProjectExplorerPlugin::findProjectFileFactory(const QString &filename) const
812 if (const Core::MimeType mt = Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(filename)))
813 if (ProjectFileFactory *pf = findFactory<ProjectFileFactory>(mt.type(), d->m_fileFactories.constBegin(), d->m_fileFactories.constEnd()))
815 qWarning("Unable to find project file factory for '%s'", filename.toUtf8().constData());
819 void ProjectExplorerPlugin::loadAction()
822 qDebug() << "ProjectExplorerPlugin::loadAction";
825 QString dir = d->m_lastOpenDirectory;
827 // for your special convenience, we preselect a pro file if it is
829 if (Core::IEditor *editor = Core::EditorManager::instance()->currentEditor()) {
830 if (const Core::IFile *file = editor->file()) {
831 const QString fn = file->fileName();
832 const bool isProject = d->m_profileMimeTypes.contains(file->mimeType());
833 dir = isProject ? fn : QFileInfo(fn).absolutePath();
837 QString filename = QFileDialog::getOpenFileName(0, tr("Load Project"),
839 d->m_projectFilterString);
840 if (filename.isEmpty())
842 if (ProjectFileFactory *pf = findProjectFileFactory(filename))
847 void ProjectExplorerPlugin::unloadProject()
850 qDebug() << "ProjectExplorerPlugin::unloadProject";
852 Core::IFile *fi = d->m_currentProject->file();
854 if (!fi || fi->fileName().isEmpty()) //nothing to save?
857 QList<Core::IFile*> filesToSave;
860 // check the number of modified files
861 int readonlycount = 0;
862 foreach (const Core::IFile *file, filesToSave) {
863 if (file->isReadOnly())
867 bool success = false;
868 if (readonlycount > 0)
869 success = Core::ICore::instance()->fileManager()->saveModifiedFiles(filesToSave).isEmpty();
871 success = Core::ICore::instance()->fileManager()->saveModifiedFilesSilently(filesToSave).isEmpty();
876 addToRecentProjects(fi->fileName(), d->m_currentProject->displayName());
877 d->m_session->removeProject(d->m_currentProject);
881 void ProjectExplorerPlugin::clearSession()
884 qDebug() << "ProjectExplorerPlugin::clearSession";
886 if (!d->m_session->clear())
887 return; // Action has been cancelled
891 void ProjectExplorerPlugin::extensionsInitialized()
893 d->m_fileFactories = ProjectFileFactory::createFactories(&d->m_projectFilterString);
894 foreach (ProjectFileFactory *pf, d->m_fileFactories) {
895 d->m_profileMimeTypes += pf->mimeTypes();
896 addAutoReleasedObject(pf);
898 // Add custom wizards, for which other plugins might have registered
900 foreach(Core::IWizard *cpw, ProjectExplorer::CustomWizard::createWizards())
901 addAutoReleasedObject(cpw);
904 void ProjectExplorerPlugin::aboutToShutdown()
906 d->m_proWindow->aboutToShutdown(); // disconnect from session
907 d->m_session->clear();
908 d->m_projectsMode = 0;
909 // d->m_proWindow->saveConfigChanges();
912 void ProjectExplorerPlugin::newProject()
915 qDebug() << "ProjectExplorerPlugin::newProject";
917 QString defaultLocation;
918 if (currentProject()) {
919 QDir dir(currentProject()->projectDirectory());
921 defaultLocation = dir.absolutePath();
924 Core::ICore::instance()->showNewItemDialog(tr("New Project", "Title of dialog"),
925 Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard),
930 void ProjectExplorerPlugin::showSessionManager()
933 qDebug() << "ProjectExplorerPlugin::showSessionManager";
935 if (d->m_session->isDefaultVirgin()) {
936 // do not save new virgin default sessions
938 d->m_session->save();
940 SessionDialog sessionDialog(d->m_session);
941 sessionDialog.exec();
945 Core::ModeManager *modeManager = Core::ModeManager::instance();
946 Core::IMode *welcomeMode = modeManager->mode(Core::Constants::MODE_WELCOME);
947 if (modeManager->currentMode() == welcomeMode)
951 void ProjectExplorerPlugin::setStartupProject(Project *project)
954 qDebug() << "ProjectExplorerPlugin::setStartupProject";
958 d->m_session->setStartupProject(project);
962 void ProjectExplorerPlugin::savePersistentSettings()
965 qDebug()<<"ProjectExplorerPlugin::savePersistentSettings()";
967 foreach (Project *pro, d->m_session->projects())
970 if (d->m_session->isDefaultVirgin()) {
971 // do not save new virgin default sessions
973 d->m_session->save();
976 QSettings *s = Core::ICore::instance()->settings();
978 s->setValue("ProjectExplorer/StartupSession", d->m_session->currentSession());
979 s->remove("ProjectExplorer/RecentProjects/Files");
981 QStringList fileNames;
982 QStringList displayNames;
983 QList<QPair<QString, QString> >::const_iterator it, end;
984 end = d->m_recentProjects.constEnd();
985 for (it = d->m_recentProjects.constBegin(); it != end; ++it) {
986 fileNames << (*it).first;
987 displayNames << (*it).second;
990 s->setValue("ProjectExplorer/RecentProjects/FileNames", fileNames);
991 s->setValue("ProjectExplorer/RecentProjects/DisplayNames", displayNames);
993 s->setValue("ProjectExplorer/Settings/BuildBeforeRun", d->m_projectExplorerSettings.buildBeforeRun);
994 s->setValue("ProjectExplorer/Settings/SaveBeforeBuild", d->m_projectExplorerSettings.saveBeforeBuild);
995 s->setValue("ProjectExplorer/Settings/ShowCompilerOutput", d->m_projectExplorerSettings.showCompilerOutput);
996 s->setValue("ProjectExplorer/Settings/CleanOldAppOutput", d->m_projectExplorerSettings.cleanOldAppOutput);
997 s->setValue("ProjectExplorer/Settings/UseJom", d->m_projectExplorerSettings.useJom);
1001 bool ProjectExplorerPlugin::openProject(const QString &fileName)
1004 qDebug() << "ProjectExplorerPlugin::openProject";
1006 QList<Project *> list = openProjects(QStringList() << fileName);
1007 if (!list.isEmpty()) {
1008 addToRecentProjects(fileName, list.first()->displayName());
1014 static inline QList<IProjectManager*> allProjectManagers()
1016 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
1017 return pm->getObjects<IProjectManager>();
1020 QList<Project *> ProjectExplorerPlugin::openProjects(const QStringList &fileNames)
1023 qDebug() << "ProjectExplorerPlugin - opening projects " << fileNames;
1025 const QList<IProjectManager*> projectManagers = allProjectManagers();
1027 QList<Project*> openedPro;
1028 foreach (const QString &fileName, fileNames) {
1029 if (const Core::MimeType mt = Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName))) {
1030 foreach (IProjectManager *manager, projectManagers) {
1031 if (manager->mimeType() == mt.type()) {
1032 if (Project *pro = manager->openProject(fileName)) {
1033 if (pro->restoreSettings()) {
1034 connect(pro, SIGNAL(fileListChanged()), this, SIGNAL(fileListChanged()));
1035 d->m_session->addProject(pro);
1036 // Make sure we always have a current project / node
1037 if (!d->m_currentProject && !openedPro.isEmpty())
1038 setCurrentNode(pro->rootProjectNode());
1044 d->m_session->reportProjectLoadingProgress();
1052 if (openedPro.isEmpty()) {
1053 qDebug() << "ProjectExplorerPlugin - Could not open any projects!";
1055 Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
1061 Project *ProjectExplorerPlugin::currentProject() const
1064 if (d->m_currentProject)
1065 qDebug() << "ProjectExplorerPlugin::currentProject returns " << d->m_currentProject->displayName();
1067 qDebug() << "ProjectExplorerPlugin::currentProject returns 0";
1069 return d->m_currentProject;
1072 Node *ProjectExplorerPlugin::currentNode() const
1074 return d->m_currentNode;
1077 void ProjectExplorerPlugin::setCurrentFile(Project *project, const QString &filePath)
1079 setCurrent(project, filePath, 0);
1082 void ProjectExplorerPlugin::setCurrentFile(const QString &filePath)
1084 Project *project = d->m_session->projectForFile(filePath);
1085 // If the file is not in any project, stay with the current project
1086 // e.g. on opening a git diff buffer, git log buffer, we don't change the project
1087 // I'm not 100% sure this is correct
1089 project = d->m_currentProject;
1090 setCurrent(project, filePath, 0);
1093 void ProjectExplorerPlugin::setCurrentNode(Node *node)
1095 setCurrent(d->m_session->projectForNode(node), QString(), node);
1098 SessionManager *ProjectExplorerPlugin::session() const
1100 return d->m_session;
1103 Project *ProjectExplorerPlugin::startupProject() const
1106 qDebug() << "ProjectExplorerPlugin::startupProject";
1108 return d->m_session->startupProject();
1111 void ProjectExplorerPlugin::updateWelcomePage()
1113 ProjectWelcomePageWidget::WelcomePageData welcomePageData;
1114 welcomePageData.sessionList = d->m_session->sessions();
1115 welcomePageData.activeSession = d->m_session->activeSession();
1116 welcomePageData.previousSession = d->m_session->lastSession();
1117 welcomePageData.projectList = d->m_recentProjects;
1118 d->m_welcomePage->setWelcomePageData(welcomePageData);
1121 void ProjectExplorerPlugin::currentModeChanged(Core::IMode *mode, Core::IMode *oldMode)
1123 if (mode && mode->id() == QLatin1String(Core::Constants::MODE_WELCOME))
1124 updateWelcomePage();
1125 if (oldMode == d->m_projectsMode)
1126 savePersistentSettings();
1129 void ProjectExplorerPlugin::determineSessionToRestoreAtStartup()
1131 QStringList sessions = d->m_session->sessions();
1132 // We have command line arguments, try to find a session in them
1133 QStringList arguments = ExtensionSystem::PluginManager::instance()->arguments();
1134 // Default to no session loading
1135 d->m_sessionToRestoreAtStartup.clear();
1136 foreach (const QString &arg, arguments) {
1137 if (sessions.contains(arg)) {
1139 d->m_sessionToRestoreAtStartup = arg;
1143 if (!d->m_sessionToRestoreAtStartup.isNull())
1144 Core::ICore::instance()->modeManager()->activateMode(Core::Constants::MODE_EDIT);
1148 \fn void ProjectExplorerPlugin::restoreSession()
1150 This method is connected to the ICore::coreOpened signal. If
1151 there was no session explicitly loaded, it creates an empty new
1152 default session and puts the list of recent projects and sessions
1153 onto the welcome page.
1155 void ProjectExplorerPlugin::restoreSession()
1158 qDebug() << "ProjectExplorerPlugin::restoreSession";
1160 // We have command line arguments, try to find a session in them
1161 QStringList arguments = ExtensionSystem::PluginManager::instance()->arguments();
1162 arguments.removeOne(d->m_sessionToRestoreAtStartup);
1164 // Restore latest session or what was passed on the command line
1165 if (d->m_sessionToRestoreAtStartup.isEmpty()) {
1166 d->m_session->createAndLoadNewDefaultSession();
1168 d->m_session->loadSession(d->m_sessionToRestoreAtStartup);
1171 // update welcome page
1172 Core::ModeManager *modeManager = Core::ModeManager::instance();
1173 connect(modeManager, SIGNAL(currentModeChanged(Core::IMode*, Core::IMode*)),
1174 this, SLOT(currentModeChanged(Core::IMode*, Core::IMode*)));
1175 connect(d->m_welcomePage, SIGNAL(requestSession(QString)), this, SLOT(loadSession(QString)));
1176 connect(d->m_welcomePage, SIGNAL(requestProject(QString)), this, SLOT(loadProject(QString)));
1178 Core::ICore::instance()->openFiles(arguments);
1183 void ProjectExplorerPlugin::loadSession(const QString &session)
1186 qDebug() << "ProjectExplorerPlugin::loadSession" << session;
1187 d->m_session->loadSession(session);
1191 void ProjectExplorerPlugin::showContextMenu(const QPoint &globalPos, Node *node)
1193 QMenu *contextMenu = 0;
1196 node = d->m_session->sessionNode();
1198 if (node->nodeType() != SessionNodeType) {
1199 Project *project = d->m_session->projectForNode(node);
1200 setCurrentNode(node);
1202 emit aboutToShowContextMenu(project, node);
1203 switch (node->nodeType()) {
1204 case ProjectNodeType:
1205 if (node->parentFolderNode() == d->m_session->sessionNode())
1206 contextMenu = d->m_projectMenu;
1208 contextMenu = d->m_subProjectMenu;
1210 case FolderNodeType:
1211 contextMenu = d->m_folderMenu;
1214 populateOpenWithMenu();
1215 contextMenu = d->m_fileMenu;
1218 qWarning("ProjectExplorerPlugin::showContextMenu - Missing handler for node type");
1220 } else { // session item
1221 emit aboutToShowContextMenu(0, node);
1223 contextMenu = d->m_sessionContextMenu;
1226 updateContextMenuActions(d->m_currentNode);
1227 if (contextMenu && contextMenu->actions().count() > 0) {
1228 contextMenu->popup(globalPos);
1232 BuildManager *ProjectExplorerPlugin::buildManager() const
1234 return d->m_buildManager;
1237 void ProjectExplorerPlugin::buildStateChanged(Project * pro)
1240 qDebug() << "buildStateChanged";
1241 qDebug() << pro->file()->fileName() << "isBuilding()" << d->m_buildManager->isBuilding(pro);
1247 void ProjectExplorerPlugin::executeRunConfiguration(RunConfiguration *runConfiguration, const QString &runMode)
1249 if (IRunControlFactory *runControlFactory = findRunControlFactory(runConfiguration, runMode)) {
1250 emit aboutToExecuteProject(runConfiguration->target()->project(), runMode);
1252 RunControl *control = runControlFactory->create(runConfiguration, runMode);
1253 startRunControl(control, runMode);
1258 void ProjectExplorerPlugin::startRunControl(RunControl *runControl, const QString &runMode)
1260 d->m_outputPane->createNewOutputWindow(runControl);
1261 if (runMode == ProjectExplorer::Constants::RUNMODE)
1262 d->m_outputPane->popup(false);
1263 d->m_outputPane->showTabFor(runControl);
1264 if (projectExplorerSettings().cleanOldAppOutput)
1265 d->m_outputPane->clearContents();
1267 connect(runControl, SIGNAL(addToOutputWindow(RunControl *, const QString &, bool)),
1268 d->m_outputPane, SLOT(appendApplicationOutput(RunControl*,const QString &, bool)));
1269 connect(runControl, SIGNAL(addToOutputWindowInline(RunControl *, const QString &, bool)),
1270 d->m_outputPane, SLOT(appendApplicationOutputInline(RunControl*,const QString &, bool)));
1271 connect(runControl, SIGNAL(appendMessage(RunControl*,QString,bool)),
1272 d->m_outputPane, SLOT(appendMessage(RunControl *, const QString &, bool)));
1274 connect(runControl, SIGNAL(finished()),
1275 this, SLOT(runControlFinished()));
1277 if (runMode == ProjectExplorer::Constants::DEBUGMODE)
1278 d->m_debuggingRunControl = runControl;
1280 runControl->start();
1284 void ProjectExplorerPlugin::buildQueueFinished(bool success)
1287 qDebug() << "buildQueueFinished()" << success;
1291 if (success && d->m_delayedRunConfiguration) {
1292 executeRunConfiguration(d->m_delayedRunConfiguration, d->m_runMode);
1294 if (d->m_buildManager->tasksAvailable())
1295 d->m_buildManager->showTaskWindow();
1297 d->m_delayedRunConfiguration = 0;
1298 d->m_runMode.clear();
1301 void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node *node)
1304 qDebug() << "ProjectExplorer - setting path to " << (node ? node->path() : filePath)
1305 << " and project to " << (project ? project->displayName() : "0");
1308 filePath = node->path();
1310 node = d->m_session->nodeForFile(filePath, project);
1312 Core::ICore *core = Core::ICore::instance();
1314 bool projectChanged = false;
1315 if (d->m_currentProject != project) {
1316 Core::Context oldContext;
1317 Core::Context newContext;
1319 if (d->m_currentProject) {
1320 oldContext.add(d->m_currentProject->projectManager()->projectContext());
1321 oldContext.add(d->m_currentProject->projectManager()->projectLanguage());
1324 newContext.add(project->projectManager()->projectContext());
1325 newContext.add(project->projectManager()->projectLanguage());
1328 core->updateAdditionalContexts(oldContext, newContext);
1330 d->m_currentProject = project;
1332 projectChanged = true;
1335 if (projectChanged || d->m_currentNode != node) {
1336 d->m_currentNode = node;
1338 qDebug() << "ProjectExplorer - currentNodeChanged(" << (node ? node->path() : "0") << ", " << (project ? project->displayName() : "0") << ")";
1339 emit currentNodeChanged(d->m_currentNode, project);
1341 if (projectChanged) {
1343 qDebug() << "ProjectExplorer - currentProjectChanged(" << (project ? project->displayName() : "0") << ")";
1344 emit currentProjectChanged(project);
1348 core->fileManager()->setCurrentFile(filePath);
1351 void ProjectExplorerPlugin::updateActions()
1354 qDebug() << "ProjectExplorerPlugin::updateActions";
1356 Project *startupProject = session()->startupProject();
1357 bool enableBuildActions = startupProject
1358 && ! (d->m_buildManager->isBuilding(startupProject))
1359 && hasBuildSettings(startupProject);
1361 bool enableBuildActionsContextMenu = d->m_currentProject
1362 && ! (d->m_buildManager->isBuilding(d->m_currentProject))
1363 && hasBuildSettings(d->m_currentProject);
1366 bool hasProjects = !d->m_session->projects().isEmpty();
1367 bool building = d->m_buildManager->isBuilding();
1368 QString projectName = startupProject ? startupProject->displayName() : QString();
1369 QString projectNameContextMenu = d->m_currentProject ? d->m_currentProject->displayName() : QString();
1372 qDebug() << "BuildManager::isBuilding()" << building;
1374 d->m_unloadAction->setParameter(projectNameContextMenu);
1376 d->m_buildAction->setParameter(projectName);
1377 d->m_rebuildAction->setParameter(projectName);
1378 d->m_cleanAction->setParameter(projectName);
1380 d->m_buildAction->setEnabled(enableBuildActions);
1381 d->m_rebuildAction->setEnabled(enableBuildActions);
1382 d->m_cleanAction->setEnabled(enableBuildActions);
1384 d->m_buildActionContextMenu->setParameter(projectNameContextMenu);
1385 d->m_rebuildActionContextMenu->setParameter(projectNameContextMenu);
1386 d->m_cleanActionContextMenu->setParameter(projectNameContextMenu);
1388 d->m_buildActionContextMenu->setEnabled(enableBuildActionsContextMenu);
1389 d->m_rebuildActionContextMenu->setEnabled(enableBuildActionsContextMenu);
1390 d->m_cleanActionContextMenu->setEnabled(enableBuildActionsContextMenu);
1392 d->m_buildProjectOnlyAction->setEnabled(enableBuildActions);
1393 d->m_rebuildProjectOnlyAction->setEnabled(enableBuildActions);
1394 d->m_cleanProjectOnlyAction->setEnabled(enableBuildActions);
1396 d->m_clearSession->setEnabled(hasProjects && !building);
1397 d->m_buildSessionAction->setEnabled(hasProjects && !building);
1398 d->m_rebuildSessionAction->setEnabled(hasProjects && !building);
1399 d->m_cleanSessionAction->setEnabled(hasProjects && !building);
1400 d->m_cancelBuildAction->setEnabled(building);
1402 d->m_projectSelectorAction->setEnabled(!session()->projects().isEmpty());
1403 d->m_projectSelectorActionMenu->setEnabled(!session()->projects().isEmpty());
1408 // NBS TODO check projectOrder()
1409 // what we want here is all the projects pro depends on
1410 QStringList ProjectExplorerPlugin::allFilesWithDependencies(Project *pro)
1413 qDebug() << "ProjectExplorerPlugin::allFilesWithDependencies(" << pro->file()->fileName() << ")";
1415 QStringList filesToSave;
1416 foreach (Project *p, d->m_session->projectOrder(pro)) {
1417 FindAllFilesVisitor filesVisitor;
1418 p->rootProjectNode()->accept(&filesVisitor);
1419 filesToSave << filesVisitor.filePaths();
1425 bool ProjectExplorerPlugin::saveModifiedFiles()
1428 qDebug() << "ProjectExplorerPlugin::saveModifiedFiles";
1430 QList<Core::IFile *> filesToSave = Core::ICore::instance()->fileManager()->modifiedFiles();
1431 if (!filesToSave.isEmpty()) {
1432 if (d->m_projectExplorerSettings.saveBeforeBuild) {
1433 Core::ICore::instance()->fileManager()->saveModifiedFilesSilently(filesToSave);
1435 bool cancelled = false;
1436 bool alwaysSave = false;
1438 Core::FileManager *fm = Core::ICore::instance()->fileManager();
1439 fm->saveModifiedFiles(filesToSave, &cancelled, QString(),
1440 tr("Always save files before build"), &alwaysSave);
1445 d->m_projectExplorerSettings.saveBeforeBuild = true;
1451 //NBS handle case where there is no activeBuildConfiguration
1452 // because someone delete all build configurations
1454 void ProjectExplorerPlugin::buildProjectOnly()
1457 qDebug() << "ProjectExplorerPlugin::buildProjectOnly";
1459 if (saveModifiedFiles())
1460 buildManager()->buildProject(session()->startupProject()->activeTarget()->activeBuildConfiguration());
1463 void ProjectExplorerPlugin::buildProject()
1466 qDebug() << "ProjectExplorerPlugin::buildProject";
1468 if (saveModifiedFiles()) {
1469 QList<BuildConfiguration *> configurations;
1470 foreach (Project *pro, d->m_session->projectOrder(session()->startupProject()))
1471 if (pro->activeTarget()->activeBuildConfiguration())
1472 configurations << pro->activeTarget()->activeBuildConfiguration();
1474 d->m_buildManager->buildProjects(configurations);
1478 void ProjectExplorerPlugin::buildProjectContextMenu()
1481 qDebug() << "ProjectExplorerPlugin::buildProjectContextMenu";
1483 if (saveModifiedFiles()) {
1484 QList<BuildConfiguration *> configurations;
1485 foreach (Project *pro, d->m_session->projectOrder(d->m_currentProject))
1486 if (pro->activeTarget()->activeBuildConfiguration())
1487 configurations << pro->activeTarget()->activeBuildConfiguration();
1489 d->m_buildManager->buildProjects(configurations);
1493 void ProjectExplorerPlugin::buildSession()
1496 qDebug() << "ProjectExplorerPlugin::buildSession";
1498 if (saveModifiedFiles()) {
1499 QList<BuildConfiguration *> configurations;
1500 foreach (Project *pro, d->m_session->projectOrder())
1501 if (pro->activeTarget()->activeBuildConfiguration())
1502 configurations << pro->activeTarget()->activeBuildConfiguration();
1503 d->m_buildManager->buildProjects(configurations);
1507 void ProjectExplorerPlugin::rebuildProjectOnly()
1510 qDebug() << "ProjectExplorerPlugin::rebuildProjectOnly";
1512 if (saveModifiedFiles()) {
1513 d->m_buildManager->cleanProject(session()->startupProject()->activeTarget()->activeBuildConfiguration());
1514 d->m_buildManager->buildProject(session()->startupProject()->activeTarget()->activeBuildConfiguration());
1518 void ProjectExplorerPlugin::rebuildProject()
1521 qDebug() << "ProjectExplorerPlugin::rebuildProject";
1523 if (saveModifiedFiles()) {
1524 const QList<Project *> &projects = d->m_session->projectOrder(session()->startupProject());
1525 QList<BuildConfiguration *> configurations;
1526 foreach (Project *pro, projects)
1527 if (pro->activeTarget()->activeBuildConfiguration())
1528 configurations << pro->activeTarget()->activeBuildConfiguration();
1530 d->m_buildManager->cleanProjects(configurations);
1531 d->m_buildManager->buildProjects(configurations);
1535 void ProjectExplorerPlugin::rebuildProjectContextMenu()
1538 qDebug() << "ProjectExplorerPlugin::rebuildProjectContextMenu";
1540 if (saveModifiedFiles()) {
1541 const QList<Project *> &projects = d->m_session->projectOrder(d->m_currentProject);
1542 QList<BuildConfiguration *> configurations;
1543 foreach (Project *pro, projects)
1544 if (pro->activeTarget()->activeBuildConfiguration())
1545 configurations << pro->activeTarget()->activeBuildConfiguration();
1547 d->m_buildManager->cleanProjects(configurations);
1548 d->m_buildManager->buildProjects(configurations);
1552 void ProjectExplorerPlugin::rebuildSession()
1555 qDebug() << "ProjectExplorerPlugin::rebuildSession";
1557 if (saveModifiedFiles()) {
1558 const QList<Project *> & projects = d->m_session->projectOrder();
1559 QList<BuildConfiguration *> configurations;
1560 foreach (Project *pro, projects)
1561 if (pro->activeTarget()->activeBuildConfiguration())
1562 configurations << pro->activeTarget()->activeBuildConfiguration();
1564 d->m_buildManager->cleanProjects(configurations);
1565 d->m_buildManager->buildProjects(configurations);
1569 void ProjectExplorerPlugin::cleanProjectOnly()
1572 qDebug() << "ProjectExplorerPlugin::cleanProjectOnly";
1574 if (saveModifiedFiles())
1575 d->m_buildManager->cleanProject(session()->startupProject()->activeTarget()->activeBuildConfiguration());
1578 void ProjectExplorerPlugin::cleanProject()
1581 qDebug() << "ProjectExplorerPlugin::cleanProject";
1583 if (saveModifiedFiles()) {
1584 const QList<Project *> & projects = d->m_session->projectOrder(session()->startupProject());
1585 QList<BuildConfiguration *> configurations;
1586 foreach (Project *pro, projects)
1587 if (pro->activeTarget()->activeBuildConfiguration())
1588 configurations << pro->activeTarget()->activeBuildConfiguration();
1589 d->m_buildManager->cleanProjects(configurations);
1593 void ProjectExplorerPlugin::cleanProjectContextMenu()
1596 qDebug() << "ProjectExplorerPlugin::cleanProjectContextMenu";
1598 if (saveModifiedFiles()) {
1599 const QList<Project *> & projects = d->m_session->projectOrder(d->m_currentProject);
1600 QList<BuildConfiguration *> configurations;
1601 foreach (Project *pro, projects)
1602 if (pro->activeTarget()->activeBuildConfiguration())
1603 configurations << pro->activeTarget()->activeBuildConfiguration();
1604 d->m_buildManager->cleanProjects(configurations);
1608 void ProjectExplorerPlugin::cleanSession()
1611 qDebug() << "ProjectExplorerPlugin::cleanSession";
1613 if (saveModifiedFiles()) {
1614 const QList<Project *> & projects = d->m_session->projectOrder();
1615 QList<BuildConfiguration *> configurations;
1616 foreach (Project *pro, projects)
1617 if (pro->activeTarget()->activeBuildConfiguration())
1618 configurations << pro->activeTarget()->activeBuildConfiguration();
1619 d->m_buildManager->cleanProjects(configurations);
1623 void ProjectExplorerPlugin::runProject()
1625 runProjectImpl(startupProject(), ProjectExplorer::Constants::RUNMODE);
1628 void ProjectExplorerPlugin::runProjectContextMenu()
1630 runProjectImpl(d->m_currentProject, ProjectExplorer::Constants::RUNMODE);
1633 bool ProjectExplorerPlugin::hasBuildSettings(Project *pro)
1635 const QList<Project *> & projects = d->m_session->projectOrder(pro);
1636 foreach(Project *project, projects)
1637 if (project->activeTarget()->activeBuildConfiguration())
1642 void ProjectExplorerPlugin::runProjectImpl(Project *pro, QString mode)
1647 if (d->m_projectExplorerSettings.buildBeforeRun && hasBuildSettings(pro)) {
1648 if (!pro->activeTarget()->activeRunConfiguration()->isEnabled()) {
1649 if (!showBuildConfigDialog())
1652 if (saveModifiedFiles()) {
1653 d->m_runMode = mode;
1654 d->m_delayedRunConfiguration = pro->activeTarget()->activeRunConfiguration();
1656 const QList<Project *> & projects = d->m_session->projectOrder(pro);
1657 QList<BuildConfiguration *> configurations;
1658 foreach(Project *project, projects)
1659 if (project->activeTarget()->activeBuildConfiguration())
1660 configurations << project->activeTarget()->activeBuildConfiguration();
1661 d->m_buildManager->buildProjects(configurations);
1666 // TODO this ignores RunConfiguration::isEnabled()
1667 if (saveModifiedFiles())
1668 executeRunConfiguration(pro->activeTarget()->activeRunConfiguration(), mode);
1672 void ProjectExplorerPlugin::debugProject()
1674 Project *pro = startupProject();
1675 if (!pro || d->m_debuggingRunControl )
1678 runProjectImpl(pro, ProjectExplorer::Constants::DEBUGMODE);
1681 bool ProjectExplorerPlugin::showBuildConfigDialog()
1683 Project *pro = startupProject();
1684 BuildConfigDialog *dialog = new BuildConfigDialog(pro,
1685 Core::ICore::instance()->mainWindow());
1687 BuildConfiguration *otherConfig = dialog->selectedBuildConfiguration();
1688 int result = dialog->result();
1689 dialog->deleteLater();
1691 case BuildConfigDialog::ChangeBuild:
1693 pro->activeTarget()->setActiveBuildConfiguration(otherConfig);
1697 case BuildConfigDialog::Cancel:
1699 case BuildConfigDialog::Continue:
1706 void ProjectExplorerPlugin::runControlFinished()
1708 if (sender() == d->m_debuggingRunControl)
1709 d->m_debuggingRunControl = 0;
1714 void ProjectExplorerPlugin::startupProjectChanged()
1716 static QPointer<Project> previousStartupProject = 0;
1717 Project *project = startupProject();
1718 if (project == previousStartupProject)
1721 if (d->m_projectsMode)
1722 d->m_projectsMode->setEnabled(project);
1724 if (previousStartupProject) {
1725 disconnect(previousStartupProject->activeTarget(), SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
1726 this, SLOT(updateRunActions()));
1728 disconnect(previousStartupProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
1729 this, SLOT(updateRunActions()));
1730 disconnect(previousStartupProject->activeTarget()->activeRunConfiguration(),
1731 SIGNAL(isEnabledChanged(bool)), this, SLOT(updateRunActions()));
1733 foreach (Target *t, previousStartupProject->targets())
1734 disconnect(t, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
1735 this, SLOT(updateActions()));
1738 previousStartupProject = project;
1741 connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
1742 this, SLOT(updateRunActions()));
1744 connect(project->activeTarget(), SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
1745 this, SLOT(updateRunActions()));
1747 if (project->activeTarget()->activeRunConfiguration()) {
1748 connect(project->activeTarget()->activeRunConfiguration(), SIGNAL(isEnabledChanged(bool)),
1749 this, SLOT(updateRunActions()));
1750 foreach (Target *t, project->targets())
1751 connect(t, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
1752 this, SLOT(updateActions()));
1759 // NBS TODO implement more than one runner
1760 IRunControlFactory *ProjectExplorerPlugin::findRunControlFactory(RunConfiguration *config, const QString &mode)
1762 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
1763 const QList<IRunControlFactory *> factories = pm->getObjects<IRunControlFactory>();
1764 foreach (IRunControlFactory *f, factories)
1765 if (f->canRun(config, mode))
1770 void ProjectExplorerPlugin::updateRunActions()
1772 const Project *project = startupProject();
1775 !project->activeTarget() ||
1776 !project->activeTarget()->activeRunConfiguration()) {
1778 d->m_runAction->setToolTip(tr("Cannot run without a project."));
1779 d->m_debugAction->setToolTip(tr("Cannot debug without a project."));
1781 d->m_runAction->setEnabled(false);
1782 d->m_debugAction->setEnabled(false);
1785 d->m_runAction->setToolTip(QString());
1786 d->m_debugAction->setToolTip(QString());
1788 RunConfiguration *activeRC = project->activeTarget()->activeRunConfiguration();
1790 bool canRun = findRunControlFactory(activeRC, ProjectExplorer::Constants::RUNMODE)
1791 && activeRC->isEnabled();
1792 const bool canDebug = !d->m_debuggingRunControl && findRunControlFactory(activeRC, ProjectExplorer::Constants::DEBUGMODE)
1793 && activeRC->isEnabled();
1794 const bool building = d->m_buildManager->isBuilding();
1796 d->m_runAction->setEnabled(canRun && !building);
1798 canRun = session()->startupProject() && findRunControlFactory(activeRC, ProjectExplorer::Constants::RUNMODE);
1800 d->m_runActionContextMenu->setEnabled(canRun && !building);
1802 d->m_debugAction->setEnabled(canDebug && !building);
1806 void ProjectExplorerPlugin::cancelBuild()
1809 qDebug() << "ProjectExplorerPlugin::cancelBuild";
1811 if (d->m_buildManager->isBuilding())
1812 d->m_buildManager->cancel();
1815 void ProjectExplorerPlugin::addToRecentProjects(const QString &fileName, const QString &displayName)
1818 qDebug() << "ProjectExplorerPlugin::addToRecentProjects(" << fileName << ")";
1820 if (fileName.isEmpty())
1822 QString prettyFileName(QDir::toNativeSeparators(fileName));
1824 QList<QPair<QString, QString> >::iterator it;
1825 for(it = d->m_recentProjects.begin(); it != d->m_recentProjects.end();)
1826 if ((*it).first == prettyFileName)
1827 it = d->m_recentProjects.erase(it);
1831 if (d->m_recentProjects.count() > d->m_maxRecentProjects)
1832 d->m_recentProjects.removeLast();
1833 d->m_recentProjects.prepend(qMakePair(prettyFileName, displayName));
1834 QFileInfo fi(prettyFileName);
1835 d->m_lastOpenDirectory = fi.absolutePath();
1838 void ProjectExplorerPlugin::updateRecentProjectMenu()
1840 typedef QList<QPair<QString, QString> >::const_iterator StringPairListConstIterator;
1842 qDebug() << "ProjectExplorerPlugin::updateRecentProjectMenu";
1844 Core::ActionContainer *aci =
1845 Core::ICore::instance()->actionManager()->actionContainer(Constants::M_RECENTPROJECTS);
1846 QMenu *menu = aci->menu();
1849 menu->setEnabled(!d->m_recentProjects.isEmpty());
1851 //projects (ignore sessions, they used to be in this list)
1852 const StringPairListConstIterator end = d->m_recentProjects.constEnd();
1853 for (StringPairListConstIterator it = d->m_recentProjects.constBegin(); it != end; ++it) {
1854 const QPair<QString, QString> &s = *it;
1855 if (s.first.endsWith(QLatin1String(".qws")))
1857 QAction *action = menu->addAction(s.first);
1858 action->setData(s.first);
1859 connect(action, SIGNAL(triggered()), this, SLOT(openRecentProject()));
1863 void ProjectExplorerPlugin::openRecentProject()
1866 qDebug() << "ProjectExplorerPlugin::openRecentProject()";
1868 QAction *a = qobject_cast<QAction*>(sender());
1871 QString fileName = a->data().toString();
1872 if (!fileName.isEmpty())
1873 openProject(fileName);
1876 void ProjectExplorerPlugin::invalidateProject(Project *project)
1879 qDebug() << "ProjectExplorerPlugin::invalidateProject" << project->displayName();
1880 if (d->m_currentProject == project) {
1882 // Workaround for a bug in QItemSelectionModel
1883 // - currentChanged etc are not emitted if the
1884 // item is removed from the underlying data model
1886 setCurrent(0, QString(), 0);
1889 disconnect(project, SIGNAL(fileListChanged()), this, SIGNAL(fileListChanged()));
1893 void ProjectExplorerPlugin::goToTaskWindow()
1895 d->m_buildManager->gotoTaskWindow();
1898 void ProjectExplorerPlugin::updateContextMenuActions(Node *node)
1900 d->m_addExistingFilesAction->setEnabled(false);
1901 d->m_addNewFileAction->setEnabled(false);
1902 d->m_removeFileAction->setEnabled(false);
1904 if (node->projectNode()) {
1905 QList<ProjectNode::ProjectAction> actions =
1906 d->m_currentNode->projectNode()->supportedActions(node);
1908 if (qobject_cast<FolderNode*>(d->m_currentNode)) {
1909 bool addFilesEnabled = actions.contains(ProjectNode::AddFile);
1910 d->m_addExistingFilesAction->setEnabled(addFilesEnabled);
1911 d->m_addNewFileAction->setEnabled(addFilesEnabled);
1912 d->m_renameFileAction->setEnabled(actions.contains(ProjectNode::Rename));
1913 } else if (qobject_cast<FileNode*>(d->m_currentNode)) {
1914 bool removeFileEnabled = actions.contains(ProjectNode::RemoveFile);
1915 d->m_removeFileAction->setEnabled(removeFileEnabled);
1916 d->m_renameFileAction->setEnabled(actions.contains(ProjectNode::Rename));
1921 void ProjectExplorerPlugin::addNewFile()
1923 QTC_ASSERT(d->m_currentNode, return)
1924 QFileInfo fi(d->m_currentNode->path());
1925 const QString location = (fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath());
1926 Core::ICore::instance()->showNewItemDialog(tr("New File", "Title of dialog"),
1927 Core::IWizard::wizardsOfKind(Core::IWizard::FileWizard)
1928 + Core::IWizard::wizardsOfKind(Core::IWizard::ClassWizard),
1932 void ProjectExplorerPlugin::addExistingFiles()
1934 QTC_ASSERT(d->m_currentNode, return)
1936 ProjectNode *projectNode = qobject_cast<ProjectNode*>(d->m_currentNode->projectNode());
1937 Core::ICore *core = Core::ICore::instance();
1938 QFileInfo fi(d->m_currentNode->path());
1939 const QString dir = (fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath());
1940 QStringList fileNames = QFileDialog::getOpenFileNames(core->mainWindow(), tr("Add Existing Files"), dir);
1941 if (fileNames.isEmpty())
1944 QHash<FileType, QString> fileTypeToFiles;
1945 foreach (const QString &fileName, fileNames) {
1946 FileType fileType = typeForFileName(core->mimeDatabase(), QFileInfo(fileName));
1947 fileTypeToFiles.insertMulti(fileType, fileName);
1950 QStringList notAdded;
1951 foreach (const FileType type, fileTypeToFiles.uniqueKeys()) {
1952 projectNode->addFiles(type, fileTypeToFiles.values(type), ¬Added);
1954 if (!notAdded.isEmpty()) {
1955 QString message = tr("Could not add following files to project %1:\n").arg(projectNode->displayName());
1956 QString files = notAdded.join("\n");
1957 QMessageBox::warning(core->mainWindow(), tr("Add files to project failed"),
1959 foreach (const QString &file, notAdded)
1960 fileNames.removeOne(file);
1963 if (Core::IVersionControl *vcManager = core->vcsManager()->findVersionControlForDirectory(dir))
1964 if (vcManager->supportsOperation(Core::IVersionControl::AddOperation)) {
1965 const QString files = fileNames.join(QString(QLatin1Char('\n')));
1966 QMessageBox::StandardButton button =
1967 QMessageBox::question(core->mainWindow(), tr("Add to Version Control"),
1968 tr("Add files\n%1\nto version control (%2)?").arg(files, vcManager->displayName()),
1969 QMessageBox::Yes | QMessageBox::No);
1970 if (button == QMessageBox::Yes) {
1971 QStringList notAddedToVc;
1972 foreach (const QString &file, fileNames) {
1973 if (!vcManager->vcsAdd(file))
1974 notAddedToVc << file;
1977 if (!notAddedToVc.isEmpty()) {
1978 const QString message = tr("Could not add following files to version control (%1)\n").arg(vcManager->displayName());
1979 const QString filesNotAdded = notAddedToVc.join(QString(QLatin1Char('\n')));
1980 QMessageBox::warning(core->mainWindow(), tr("Add files to version control failed"),
1981 message + filesNotAdded);
1987 void ProjectExplorerPlugin::openFile()
1989 QTC_ASSERT(d->m_currentNode, return)
1990 Core::EditorManager *em = Core::EditorManager::instance();
1991 em->openEditor(d->m_currentNode->path());
1992 em->ensureEditorManagerVisible();
1995 void ProjectExplorerPlugin::showInGraphicalShell()
1997 QTC_ASSERT(d->m_currentNode, return)
1998 FolderNavigationWidget::showInGraphicalShell(Core::ICore::instance()->mainWindow(),
1999 d->m_currentNode->path());
2002 void ProjectExplorerPlugin::openTerminalHere()
2004 QTC_ASSERT(d->m_currentNode, return)
2005 FolderNavigationWidget::openTerminal(d->m_currentNode->path());
2008 void ProjectExplorerPlugin::removeFile()
2010 QTC_ASSERT(d->m_currentNode && d->m_currentNode->nodeType() == FileNodeType, return)
2012 FileNode *fileNode = qobject_cast<FileNode*>(d->m_currentNode);
2013 Core::ICore *core = Core::ICore::instance();
2015 QString filePath = d->m_currentNode->path();
2016 RemoveFileDialog removeFileDialog(filePath, core->mainWindow());
2018 if (removeFileDialog.exec() == QDialog::Accepted) {
2019 const bool deleteFile = removeFileDialog.isDeleteFileChecked();
2021 // remove from project
2022 ProjectNode *projectNode = fileNode->projectNode();
2023 Q_ASSERT(projectNode);
2025 if (!projectNode->removeFiles(fileNode->fileType(), QStringList(filePath))) {
2026 QMessageBox::warning(core->mainWindow(), tr("Remove file failed"),
2027 tr("Could not remove file %1 from project %2.").arg(filePath).arg(projectNode->displayName()));
2031 // remove from version control
2032 core->vcsManager()->promptToDelete(filePath);
2034 // remove from file system
2036 QFile file(filePath);
2038 if (file.exists()) {
2039 // could have been deleted by vc
2041 QMessageBox::warning(core->mainWindow(), tr("Delete file failed"),
2042 tr("Could not delete file %1.").arg(filePath));
2048 void ProjectExplorerPlugin::renameFile()
2050 QWidget *focusWidget = QApplication::focusWidget();
2051 while (focusWidget) {
2052 ProjectTreeWidget *treeWidget = qobject_cast<ProjectTreeWidget*>(focusWidget);
2054 treeWidget->editCurrentItem();
2057 focusWidget = focusWidget->parentWidget();
2061 void ProjectExplorerPlugin::renameFile(Node *node, const QString &to)
2063 FileNode *fileNode = qobject_cast<FileNode *>(node);
2066 QString orgFilePath = node->path();
2067 QString dir = QFileInfo(orgFilePath).absolutePath();
2068 QString newFilePath = dir + "/" + to;
2069 Core::ICore *core = Core::ICore::instance();
2070 Core::IVersionControl *vc = core->vcsManager()->findVersionControlForDirectory(dir);
2071 bool result = false;
2072 if (vc && vc->supportsOperation(Core::IVersionControl::MoveOperation))
2073 result = vc->vcsMove(orgFilePath, newFilePath);
2074 if (!result) // The moving via vcs failed or the vcs does not support moving, fall back
2075 result = QFile::rename(orgFilePath, newFilePath);
2077 // yeah we moved, tell the filemanager about it
2078 Core::ICore::instance()->fileManager()->renamedFile(orgFilePath, newFilePath);
2079 // Tell the project plugin about it
2080 ProjectNode *projectNode = fileNode->projectNode();
2081 projectNode->renameFile(fileNode->fileType(), orgFilePath, newFilePath);
2082 // TODO emit a signal?
2086 void ProjectExplorerPlugin::populateOpenWithMenu(QMenu *menu, const QString &fileName)
2088 typedef QList<Core::IEditorFactory*> EditorFactoryList;
2089 typedef QList<Core::IExternalEditor*> ExternalEditorList;
2093 bool anyMatches = false;
2095 Core::ICore *core = Core::ICore::instance();
2096 if (const Core::MimeType mt = core->mimeDatabase()->findByFile(QFileInfo(fileName))) {
2097 const EditorFactoryList factories = core->editorManager()->editorFactories(mt, false);
2098 const ExternalEditorList externalEditors = core->editorManager()->externalEditors(mt, false);
2099 anyMatches = !factories.empty() || !externalEditors.empty();
2101 const QList<Core::IEditor *> editorsOpenForFile = core->editorManager()->editorsForFileName(fileName);
2102 // Add all suitable editors
2103 foreach (Core::IEditorFactory *editorFactory, factories) {
2104 // Add action to open with this very editor factory
2105 QString const actionTitle = editorFactory->displayName();
2106 QAction * const action = menu->addAction(actionTitle);
2107 action->setData(qVariantFromValue(editorFactory));
2108 // File already open in an editor -> only enable that entry since
2109 // we currently do not support opening a file in two editors at once
2110 if (!editorsOpenForFile.isEmpty()) {
2111 bool enabled = false;
2112 foreach (Core::IEditor * const openEditor, editorsOpenForFile) {
2113 if (editorFactory->id() == openEditor->id())
2117 action->setEnabled(enabled);
2119 } // for editor factories
2120 // Add all suitable external editors
2121 foreach (Core::IExternalEditor *externalEditor, externalEditors) {
2122 QAction * const action = menu->addAction(externalEditor->displayName());
2123 action->setData(qVariantFromValue(externalEditor));
2127 menu->setEnabled(anyMatches);
2130 void ProjectExplorerPlugin::populateOpenWithMenu()
2132 populateOpenWithMenu(d->m_openWithMenu, currentNode()->path());
2135 void ProjectExplorerPlugin::openWithMenuTriggered(QAction *action)
2138 qWarning() << "ProjectExplorerPlugin::openWithMenuTriggered no action, can't happen.";
2140 openEditorFromAction(action, currentNode()->path());
2143 void ProjectExplorerPlugin::openEditorFromAction(QAction *action, const QString &fileName)
2145 Core::EditorManager *em = Core::EditorManager::instance();
2146 const QVariant data = action->data();
2147 if (qVariantCanConvert<Core::IEditorFactory *>(data)) {
2148 Core::IEditorFactory *factory = qVariantValue<Core::IEditorFactory *>(data);
2149 em->openEditor(fileName, factory->id());
2150 em->ensureEditorManagerVisible();
2153 if (qVariantCanConvert<Core::IExternalEditor *>(data)) {
2154 Core::IExternalEditor *externalEditor = qVariantValue<Core::IExternalEditor *>(data);
2155 em->openExternalEditor(fileName, externalEditor->id());
2159 void ProjectExplorerPlugin::updateSessionMenu()
2161 d->m_sessionMenu->clear();
2162 QActionGroup *ag = new QActionGroup(d->m_sessionMenu);
2163 connect(ag, SIGNAL(triggered(QAction *)), this, SLOT(setSession(QAction *)));
2164 const QString &activeSession = d->m_session->activeSession();
2165 foreach (const QString &session, d->m_session->sessions()) {
2166 QAction *act = ag->addAction(session);
2167 act->setCheckable(true);
2168 if (session == activeSession)
2169 act->setChecked(true);
2171 d->m_sessionMenu->addActions(ag->actions());
2172 d->m_sessionMenu->addSeparator();
2173 d->m_sessionMenu->addAction(d->m_sessionManagerAction);
2175 d->m_sessionMenu->setEnabled(true);
2178 void ProjectExplorerPlugin::setSession(QAction *action)
2180 QString session = action->text();
2181 if (session != d->m_session->activeSession())
2182 d->m_session->loadSession(session);
2186 void ProjectExplorerPlugin::setProjectExplorerSettings(const Internal::ProjectExplorerSettings &pes)
2188 if (d->m_projectExplorerSettings == pes)
2190 d->m_projectExplorerSettings = pes;
2191 emit settingsChanged();
2194 Internal::ProjectExplorerSettings ProjectExplorerPlugin::projectExplorerSettings() const
2196 return d->m_projectExplorerSettings;
2199 QStringList ProjectExplorerPlugin::projectFilePatterns()
2201 QStringList patterns;
2202 const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase();
2203 foreach(const IProjectManager *pm, allProjectManagers())
2204 if (const Core::MimeType mt = mdb->findByType(pm->mimeType()))
2205 foreach(const QRegExp &re, mt.globPatterns())
2206 patterns += re.pattern();
2210 void ProjectExplorerPlugin::openOpenProjectDialog()
2212 Core::FileManager *fileMananger = Core::ICore::instance()->fileManager();
2213 const QString projectPatterns = ProjectExplorerPlugin::projectFilePatterns().join(QString(QLatin1Char(' ')));
2214 QString projectFilesFilter = tr("Projects (%1)").arg(projectPatterns);
2215 const QString allFilesFilter = tr("All Files (*)");
2216 const QString filters = allFilesFilter + QLatin1String(";;") + projectFilesFilter;
2217 const QString path = fileMananger->useProjectsDirectory() ? fileMananger->projectsDirectory() : QString();
2218 const QStringList files = fileMananger->getOpenFileNames(filters, path, &projectFilesFilter);
2219 if (!files.isEmpty())
2220 Core::ICore::instance()->openFiles(files);
2223 Q_EXPORT_PLUGIN(ProjectExplorerPlugin)