OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / projectexplorer / projectexplorer.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
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.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "projectexplorer.h"
35
36 #include "buildsteplist.h"
37 #include "deployconfiguration.h"
38 #include "project.h"
39 #include "projectexplorersettings.h"
40 #include "target.h"
41 #include "targetsettingspanel.h"
42 #include "copytaskhandler.h"
43 #include "showineditortaskhandler.h"
44 #include "vcsannotatetaskhandler.h"
45 #include "localapplicationruncontrol.h"
46 #include "allprojectsfilter.h"
47 #include "allprojectsfind.h"
48 #include "buildmanager.h"
49 #include "buildsettingspropertiespage.h"
50 #include "currentprojectfind.h"
51 #include "currentprojectfilter.h"
52 #include "customexecutablerunconfiguration.h"
53 #include "editorsettingspropertiespage.h"
54 #include "dependenciespanel.h"
55 #include "foldernavigationwidget.h"
56 #include "iprojectmanager.h"
57 #include "metatypedeclarations.h"
58 #include "nodesvisitor.h"
59 #include "outputwindow.h"
60 #include "persistentsettings.h"
61 #include "pluginfilefactory.h"
62 #include "processstep.h"
63 #include "projectexplorerconstants.h"
64 #include "customwizard.h"
65 #include "projectfilewizardextension.h"
66 #include "projecttreewidget.h"
67 #include "projectwindow.h"
68 #include "removefiledialog.h"
69 #include "runsettingspropertiespage.h"
70 #include "scriptwrappers.h"
71 #include "session.h"
72 #include "projectnodes.h"
73 #include "sessiondialog.h"
74 #include "target.h"
75 #include "projectexplorersettingspage.h"
76 #include "projectwelcomepage.h"
77 #include "projectwelcomepagewidget.h"
78 #include "corelistenercheckingforrunningbuild.h"
79 #include "buildconfiguration.h"
80 #include "miniprojecttargetselector.h"
81 #include "taskhub.h"
82 #include "publishing/ipublishingwizardfactory.h"
83 #include "publishing/publishingwizardselectiondialog.h"
84
85 #include <coreplugin/coreconstants.h>
86 #include <coreplugin/filemanager.h>
87 #include <coreplugin/icore.h>
88 #include <coreplugin/imode.h>
89 #include <coreplugin/mimedatabase.h>
90 #include <coreplugin/modemanager.h>
91 #include <coreplugin/actionmanager/actionmanager.h>
92 #include <coreplugin/actionmanager/actioncontainer.h>
93 #include <coreplugin/actionmanager/command.h>
94 #include <coreplugin/uniqueidmanager.h>
95 #include <coreplugin/editormanager/editormanager.h>
96 #include <coreplugin/editormanager/ieditor.h>
97 #include <coreplugin/editormanager/ieditorfactory.h>
98 #include <coreplugin/editormanager/iexternaleditor.h>
99 #include <coreplugin/findplaceholder.h>
100 #include <coreplugin/basefilewizard.h>
101 #include <coreplugin/vcsmanager.h>
102 #include <coreplugin/iversioncontrol.h>
103 #include <welcome/welcomemode.h>
104 #include <extensionsystem/pluginmanager.h>
105 #include <find/searchresultwindow.h>
106 #include <utils/consoleprocess.h>
107 #include <utils/qtcassert.h>
108 #include <utils/parameteraction.h>
109 #include <utils/stringutils.h>
110
111 #include <QtCore/QtPlugin>
112 #include <QtCore/QDateTime>
113 #include <QtCore/QDebug>
114 #include <QtCore/QSettings>
115
116 #include <QtGui/QAction>
117 #include <QtGui/QApplication>
118 #include <QtGui/QFileDialog>
119 #include <QtGui/QMenu>
120 #include <QtGui/QMessageBox>
121 #include <QtGui/QMainWindow>
122 #include <QtGui/QWizard>
123
124 Q_DECLARE_METATYPE(Core::IEditorFactory*)
125 Q_DECLARE_METATYPE(Core::IExternalEditor*)
126
127 namespace {
128 bool debug = false;
129 }
130
131 namespace ProjectExplorer {
132
133 struct ProjectExplorerPluginPrivate {
134     ProjectExplorerPluginPrivate();
135
136     QMenu *m_sessionContextMenu;
137     QMenu *m_sessionMenu;
138     QMenu *m_projectMenu;
139     QMenu *m_subProjectMenu;
140     QMenu *m_folderMenu;
141     QMenu *m_fileMenu;
142     QMenu *m_openWithMenu;
143
144     QMultiMap<int, QObject*> m_actionMap;
145     QAction *m_sessionManagerAction;
146     QAction *m_newAction;
147     QAction *m_loadAction;
148     Utils::ParameterAction *m_unloadAction;
149     QAction *m_clearSession;
150     QAction *m_buildProjectOnlyAction;
151     Utils::ParameterAction *m_buildAction;
152     Utils::ParameterAction *m_buildActionContextMenu;
153     QAction *m_buildSessionAction;
154     QAction *m_rebuildProjectOnlyAction;
155     Utils::ParameterAction *m_rebuildAction;
156     Utils::ParameterAction *m_rebuildActionContextMenu;
157     QAction *m_rebuildSessionAction;
158     QAction *m_cleanProjectOnlyAction;
159     QAction *m_deployProjectOnlyAction;
160     Utils::ParameterAction *m_deployAction;
161     Utils::ParameterAction *m_deployActionContextMenu;
162     QAction *m_deploySessionAction;
163     Utils::ParameterAction *m_publishAction;
164     Utils::ParameterAction *m_cleanAction;
165     Utils::ParameterAction *m_cleanActionContextMenu;
166     QAction *m_cleanSessionAction;
167     QAction *m_runAction;
168     QAction *m_runActionContextMenu;
169     QAction *m_cancelBuildAction;
170     QAction *m_addNewFileAction;
171     QAction *m_addExistingFilesAction;
172     QAction *m_addNewSubprojectAction;
173     QAction *m_removeFileAction;
174     QAction *m_removeProjectAction;
175     QAction *m_deleteFileAction;
176     QAction *m_renameFileAction;
177     QAction *m_openFileAction;
178     QAction *m_showInGraphicalShell;
179     QAction *m_openTerminalHere;
180     QAction *m_setStartupProjectAction;
181     QAction *m_projectSelectorAction;
182     QAction *m_projectSelectorActionMenu;
183
184     Internal::ProjectWindow *m_proWindow;
185     SessionManager *m_session;
186     QString m_sessionToRestoreAtStartup;
187
188     Project *m_currentProject;
189     Node *m_currentNode;
190
191     BuildManager *m_buildManager;
192
193     QList<Internal::ProjectFileFactory*> m_fileFactories;
194     QStringList m_profileMimeTypes;
195     Internal::OutputPane *m_outputPane;
196
197     QList<QPair<QString, QString> > m_recentProjects; // pair of filename, displayname
198     static const int m_maxRecentProjects = 7;
199
200     QString m_lastOpenDirectory;
201     RunConfiguration *m_delayedRunConfiguration; // TODO this is not right
202     QString m_runMode;
203     QString m_projectFilterString;
204     Internal::MiniProjectTargetSelector * m_targetSelector;
205     Internal::ProjectExplorerSettings m_projectExplorerSettings;
206     Internal::ProjectWelcomePage *m_welcomePage;
207
208     Core::IMode *m_projectsMode;
209 };
210
211 ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() :
212     m_currentProject(0),
213     m_currentNode(0),
214     m_delayedRunConfiguration(0),
215     m_projectsMode(0)
216 {
217 }
218
219 class ProjectsMode : public Core::IMode
220 {
221 public:
222     ProjectsMode(QWidget *proWindow) : m_widget(proWindow) {}
223
224     QString displayName() const { return tr("Projects"); }
225     QIcon icon() const { return QIcon(QLatin1String(":/fancyactionbar/images/mode_Project.png")); }
226     int priority() const { return Constants::P_MODE_SESSION; }
227     QWidget *widget() { return m_widget; }
228     QString id() const { return QLatin1String(Constants::MODE_SESSION); }
229     QString type() const { return QString(); }
230     Core::Context context() const { return Core::Context(Constants::C_PROJECTEXPLORER); }
231     QString contextHelpId() const { return QLatin1String("Managing Projects"); }
232
233 private:
234     QWidget *m_widget;
235     QIcon m_icon;
236 };
237
238 }  // namespace ProjectExplorer
239
240 using namespace ProjectExplorer;
241 using namespace ProjectExplorer::Internal;
242
243
244 ProjectExplorerPlugin *ProjectExplorerPlugin::m_instance = 0;
245
246 ProjectExplorerPlugin::ProjectExplorerPlugin()
247     : d(new ProjectExplorerPluginPrivate)
248 {
249     m_instance = this;
250 }
251
252 ProjectExplorerPlugin::~ProjectExplorerPlugin()
253 {
254     removeObject(d->m_welcomePage);
255     delete d->m_welcomePage;
256     removeObject(this);
257     delete d;
258 }
259
260 ProjectExplorerPlugin *ProjectExplorerPlugin::instance()
261 {
262     return m_instance;
263 }
264
265 bool ProjectExplorerPlugin::parseArguments(const QStringList &arguments, QString * /* error */)
266 {
267     CustomWizard::setVerbose(arguments.count(QLatin1String("-customwizard-verbose")));
268     return true;
269 }
270
271 bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *error)
272 {
273     if (!parseArguments(arguments, error))
274         return false;
275     addObject(this);
276
277     addAutoReleasedObject(new TaskHub);
278
279     Core::ICore *core = Core::ICore::instance();
280     Core::ActionManager *am = core->actionManager();
281     connect(core, SIGNAL(newItemsDialogRequested()), this, SLOT(loadCustomWizards()));
282
283     d->m_welcomePage = new ProjectWelcomePage;
284     connect(d->m_welcomePage, SIGNAL(manageSessions()), this, SLOT(showSessionManager()));
285     addObject(d->m_welcomePage);
286
287     connect(core->fileManager(), SIGNAL(currentFileChanged(QString)),
288             this, SLOT(setCurrentFile(QString)));
289
290     d->m_session = new SessionManager(this);
291
292     connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project *)),
293             this, SIGNAL(fileListChanged()));
294     connect(d->m_session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project *)),
295             this, SLOT(invalidateProject(ProjectExplorer::Project *)));
296     connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project *)),
297             this, SIGNAL(fileListChanged()));
298     connect(d->m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project *)),
299             this, SLOT(startupProjectChanged()));
300     connect(d->m_session, SIGNAL(dependencyChanged(ProjectExplorer::Project*,ProjectExplorer::Project*)),
301             this, SLOT(updateActions()));
302
303     d->m_proWindow = new ProjectWindow;
304
305     Core::Context globalcontext(Core::Constants::C_GLOBAL);
306     Core::Context projecTreeContext(Constants::C_PROJECT_TREE);
307
308     d->m_projectsMode = new ProjectsMode(d->m_proWindow);
309     d->m_projectsMode->setEnabled(session()->startupProject());
310     addAutoReleasedObject(d->m_projectsMode);
311     d->m_proWindow->layout()->addWidget(new Core::FindToolBarPlaceHolder(d->m_proWindow));
312
313     addAutoReleasedObject(new CopyTaskHandler);
314     addAutoReleasedObject(new ShowInEditorTaskHandler);
315     addAutoReleasedObject(new VcsAnnotateTaskHandler);
316
317     d->m_buildManager = new BuildManager(this);
318     connect(d->m_buildManager, SIGNAL(buildStateChanged(ProjectExplorer::Project *)),
319             this, SLOT(buildStateChanged(ProjectExplorer::Project *)));
320     connect(d->m_buildManager, SIGNAL(buildQueueFinished(bool)),
321             this, SLOT(buildQueueFinished(bool)));
322
323     addAutoReleasedObject(new CoreListener);
324
325     d->m_outputPane = new OutputPane;
326     addAutoReleasedObject(d->m_outputPane);
327     connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project *)),
328             d->m_outputPane, SLOT(projectRemoved()));
329
330     AllProjectsFilter *allProjectsFilter = new AllProjectsFilter(this);
331     addAutoReleasedObject(allProjectsFilter);
332
333     CurrentProjectFilter *currentProjectFilter = new CurrentProjectFilter(this);
334     addAutoReleasedObject(currentProjectFilter);
335
336     addAutoReleasedObject(new BuildSettingsPanelFactory);
337     addAutoReleasedObject(new RunSettingsPanelFactory);
338     addAutoReleasedObject(new EditorSettingsPanelFactory);
339     addAutoReleasedObject(new DependenciesPanelFactory(d->m_session));
340
341     ProcessStepFactory *processStepFactory = new ProcessStepFactory;
342     addAutoReleasedObject(processStepFactory);
343
344     AllProjectsFind *allProjectsFind = new AllProjectsFind(this,
345         Find::SearchResultWindow::instance());
346     addAutoReleasedObject(allProjectsFind);
347
348     CurrentProjectFind *currentProjectFind = new CurrentProjectFind(this,
349         Find::SearchResultWindow::instance());
350     addAutoReleasedObject(currentProjectFind);
351
352     addAutoReleasedObject(new LocalApplicationRunControlFactory);
353     addAutoReleasedObject(new CustomExecutableRunConfigurationFactory);
354
355     addAutoReleasedObject(new ProjectFileWizardExtension);
356
357     // Settings page
358     addAutoReleasedObject(new ProjectExplorerSettingsPage);
359
360     // context menus
361     Core::ActionContainer *msessionContextMenu =
362         am->createMenu(Constants::M_SESSIONCONTEXT);
363     Core::ActionContainer *mprojectContextMenu =
364         am->createMenu(Constants::M_PROJECTCONTEXT);
365     Core::ActionContainer *msubProjectContextMenu =
366         am->createMenu(Constants::M_SUBPROJECTCONTEXT);
367     Core::ActionContainer *mfolderContextMenu =
368         am->createMenu(Constants::M_FOLDERCONTEXT);
369     Core::ActionContainer *mfileContextMenu =
370         am->createMenu(Constants::M_FILECONTEXT);
371
372     d->m_sessionContextMenu = msessionContextMenu->menu();
373     d->m_projectMenu = mprojectContextMenu->menu();
374     d->m_subProjectMenu = msubProjectContextMenu->menu();
375     d->m_folderMenu = mfolderContextMenu->menu();
376     d->m_fileMenu = mfileContextMenu->menu();
377
378     Core::ActionContainer *mfile =
379         am->actionContainer(Core::Constants::M_FILE);
380     Core::ActionContainer *menubar =
381         am->actionContainer(Core::Constants::MENU_BAR);
382
383     // mode manager (for fancy actions)
384     Core::ModeManager *modeManager = core->modeManager();
385
386     // build menu
387     Core::ActionContainer *mbuild =
388         am->createMenu(Constants::M_BUILDPROJECT);
389     mbuild->menu()->setTitle(tr("&Build"));
390     menubar->addMenu(mbuild, Core::Constants::G_VIEW);
391
392     // debug menu
393     Core::ActionContainer *mdebug =
394         am->createMenu(Constants::M_DEBUG);
395     mdebug->menu()->setTitle(tr("&Debug"));
396     menubar->addMenu(mdebug, Core::Constants::G_VIEW);
397
398     Core::ActionContainer *mstartdebugging =
399         am->createMenu(Constants::M_DEBUG_STARTDEBUGGING);
400     mstartdebugging->menu()->setTitle(tr("&Start Debugging"));
401     mdebug->addMenu(mstartdebugging, Core::Constants::G_DEFAULT_ONE);
402
403     //
404     // Groups
405     //
406
407     mbuild->appendGroup(Constants::G_BUILD_SESSION);
408     mbuild->appendGroup(Constants::G_BUILD_PROJECT);
409     mbuild->appendGroup(Constants::G_BUILD_OTHER);
410     mbuild->appendGroup(Constants::G_BUILD_CANCEL);
411     mbuild->appendGroup(Constants::G_BUILD_RUN);
412
413     msessionContextMenu->appendGroup(Constants::G_SESSION_BUILD);
414     msessionContextMenu->appendGroup(Constants::G_SESSION_FILES);
415     msessionContextMenu->appendGroup(Constants::G_SESSION_OTHER);
416     msessionContextMenu->appendGroup(Constants::G_SESSION_CONFIG);
417
418     mprojectContextMenu->appendGroup(Constants::G_PROJECT_FIRST);
419     mprojectContextMenu->appendGroup(Constants::G_PROJECT_BUILD);
420     mprojectContextMenu->appendGroup(Constants::G_PROJECT_RUN);
421     mprojectContextMenu->appendGroup(Constants::G_PROJECT_FILES);
422     mprojectContextMenu->appendGroup(Constants::G_PROJECT_OTHER);
423     mprojectContextMenu->appendGroup(Constants::G_PROJECT_CONFIG);
424
425     msubProjectContextMenu->appendGroup(Constants::G_PROJECT_FIRST);
426     msubProjectContextMenu->appendGroup(Constants::G_PROJECT_BUILD);
427     msubProjectContextMenu->appendGroup(Constants::G_PROJECT_FILES);
428     msubProjectContextMenu->appendGroup(Constants::G_PROJECT_OTHER);
429     msubProjectContextMenu->appendGroup(Constants::G_PROJECT_CONFIG);
430
431     mfolderContextMenu->appendGroup(Constants::G_FOLDER_FILES);
432     mfolderContextMenu->appendGroup(Constants::G_FOLDER_OTHER);
433     mfolderContextMenu->appendGroup(Constants::G_FOLDER_CONFIG);
434
435     mfileContextMenu->appendGroup(Constants::G_FILE_OPEN);
436     mfileContextMenu->appendGroup(Constants::G_FILE_OTHER);
437     mfileContextMenu->appendGroup(Constants::G_FILE_CONFIG);
438
439     // "open with" submenu
440     Core::ActionContainer * const openWith =
441             am->createMenu(ProjectExplorer::Constants::M_OPENFILEWITHCONTEXT);
442     openWith->setOnAllDisabledBehavior(Core::ActionContainer::Show);
443     d->m_openWithMenu = openWith->menu();
444     d->m_openWithMenu->setTitle(tr("Open With"));
445
446     connect(d->m_openWithMenu, SIGNAL(triggered(QAction *)),
447             this, SLOT(openWithMenuTriggered(QAction *)));
448
449     //
450     // Separators
451     //
452
453     Core::Command *cmd;
454     QAction *sep;
455
456     sep = new QAction(this);
457     sep->setSeparator(true);
458     cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Build.Sep"), globalcontext);
459     mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
460
461     sep = new QAction(this);
462     sep->setSeparator(true);
463     cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Files.Sep"), projecTreeContext);
464     msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
465     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
466     msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
467
468     sep = new QAction(this);
469     sep->setSeparator(true);
470     cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Config.Sep"), projecTreeContext);
471     msessionContextMenu->addAction(cmd, Constants::G_SESSION_CONFIG);
472     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_CONFIG);
473     msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_CONFIG);
474
475     sep = new QAction(this);
476     sep->setSeparator(true);
477     cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Projects.Sep"), globalcontext);
478     mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
479
480     sep = new QAction(this);
481     sep->setSeparator(true);
482     cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Other.Sep"), globalcontext);
483     mbuild->addAction(cmd, Constants::G_BUILD_OTHER);
484     msessionContextMenu->addAction(cmd, Constants::G_SESSION_OTHER);
485     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_OTHER);
486     msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_OTHER);
487
488     sep = new QAction(this);
489     sep->setSeparator(true);
490     cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Run.Sep"), globalcontext);
491     mbuild->addAction(cmd, Constants::G_BUILD_RUN);
492     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
493
494     sep = new QAction(this);
495     sep->setSeparator(true);
496     cmd = am->registerAction(sep, Core::Id("ProjectExplorer.CancelBuild.Sep"), globalcontext);
497     mbuild->addAction(cmd, Constants::G_BUILD_CANCEL);
498
499     //
500     // Actions
501     //
502
503     // new session action
504     d->m_sessionManagerAction = new QAction(tr("Session Manager..."), this);
505     cmd = am->registerAction(d->m_sessionManagerAction, Constants::NEWSESSION, globalcontext);
506     cmd->setDefaultKeySequence(QKeySequence());
507
508     // new action
509     d->m_newAction = new QAction(tr("New Project..."), this);
510     cmd = am->registerAction(d->m_newAction, Constants::NEWPROJECT, globalcontext);
511     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+N")));
512     msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
513
514     // open action
515     d->m_loadAction = new QAction(tr("Load Project..."), this);
516     cmd = am->registerAction(d->m_loadAction, Constants::LOAD, globalcontext);
517 #ifndef Q_WS_MAC
518     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+O")));
519 #endif
520     msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
521
522     // Default open action
523     d->m_openFileAction = new QAction(tr("Open File"), this);
524     cmd = am->registerAction(d->m_openFileAction, ProjectExplorer::Constants::OPENFILE,
525                        projecTreeContext);
526     mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
527
528     d->m_showInGraphicalShell = new QAction(FolderNavigationWidget::msgGraphicalShellAction(), this);
529     cmd = am->registerAction(d->m_showInGraphicalShell, ProjectExplorer::Constants::SHOWINGRAPHICALSHELL,
530                        projecTreeContext);
531     mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
532     mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
533
534     d->m_openTerminalHere = new QAction(FolderNavigationWidget::msgTerminalAction(), this);
535     cmd = am->registerAction(d->m_openTerminalHere, ProjectExplorer::Constants::OPENTERMIANLHERE,
536                        projecTreeContext);
537     mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
538     mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
539
540     // Open With menu
541     mfileContextMenu->addMenu(openWith, ProjectExplorer::Constants::G_FILE_OPEN);
542
543     // recent projects menu
544     Core::ActionContainer *mrecent =
545         am->createMenu(Constants::M_RECENTPROJECTS);
546     mrecent->menu()->setTitle(tr("Recent P&rojects"));
547     mrecent->setOnAllDisabledBehavior(Core::ActionContainer::Show);
548     mfile->addMenu(mrecent, Core::Constants::G_FILE_OPEN);
549     connect(mfile->menu(), SIGNAL(aboutToShow()),
550         this, SLOT(updateRecentProjectMenu()));
551
552     // XXX same action?
553     // unload action
554     d->m_unloadAction = new Utils::ParameterAction(tr("Close Project"), tr("Close Project \"%1\""),
555                                                       Utils::ParameterAction::EnabledWithParameter, this);
556     cmd = am->registerAction(d->m_unloadAction, Constants::UNLOAD, globalcontext);
557     cmd->setAttribute(Core::Command::CA_UpdateText);
558     cmd->setDefaultText(d->m_unloadAction->text());
559     mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
560
561     // unload session action
562     d->m_clearSession = new QAction(tr("Close All Projects"), this);
563     cmd = am->registerAction(d->m_clearSession, Constants::CLEARSESSION, globalcontext);
564     mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
565     msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
566
567     // session menu
568     Core::ActionContainer *msession = am->createMenu(Constants::M_SESSION);
569     msession->menu()->setTitle(tr("Session"));
570     msession->setOnAllDisabledBehavior(Core::ActionContainer::Show);
571     mfile->addMenu(msession, Core::Constants::G_FILE_PROJECT);
572     d->m_sessionMenu = msession->menu();
573     connect(mfile->menu(), SIGNAL(aboutToShow()),
574             this, SLOT(updateSessionMenu()));
575
576     // build session action
577     QIcon buildIcon(Constants::ICON_BUILD);
578     buildIcon.addFile(Constants::ICON_BUILD_SMALL);
579     d->m_buildSessionAction = new QAction(buildIcon, tr("Build All"), this);
580     cmd = am->registerAction(d->m_buildSessionAction, Constants::BUILDSESSION, globalcontext);
581     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+B")));
582     mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
583     msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
584     // Add to mode bar
585     modeManager->addAction(cmd, Constants::P_ACTION_BUILDSESSION);
586
587     // rebuild session action
588     QIcon rebuildIcon(Constants::ICON_REBUILD);
589     rebuildIcon.addFile(Constants::ICON_REBUILD_SMALL);
590     d->m_rebuildSessionAction = new QAction(rebuildIcon, tr("Rebuild All"), this);
591     cmd = am->registerAction(d->m_rebuildSessionAction, Constants::REBUILDSESSION, globalcontext);
592     mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
593     msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
594
595     // deploy session
596     d->m_deploySessionAction = new QAction(tr("Deploy All"), this);
597     cmd = am->registerAction(d->m_deploySessionAction, Constants::DEPLOYSESSION, globalcontext);
598     mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
599     msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
600
601     // clean session
602     QIcon cleanIcon(Constants::ICON_CLEAN);
603     cleanIcon.addFile(Constants::ICON_CLEAN_SMALL);
604     d->m_cleanSessionAction = new QAction(cleanIcon, tr("Clean All"), this);
605     cmd = am->registerAction(d->m_cleanSessionAction, Constants::CLEANSESSION, globalcontext);
606     mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
607     msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
608
609     // build action
610     d->m_buildAction = new Utils::ParameterAction(tr("Build Project"), tr("Build Project \"%1\""),
611                                                      Utils::ParameterAction::AlwaysEnabled, this);
612     cmd = am->registerAction(d->m_buildAction, Constants::BUILD, globalcontext);
613     cmd->setAttribute(Core::Command::CA_UpdateText);
614     cmd->setDefaultText(d->m_buildAction->text());
615     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+B")));
616     mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
617
618     // rebuild action
619     d->m_rebuildAction = new Utils::ParameterAction(tr("Rebuild Project"), tr("Rebuild Project \"%1\""),
620                                                        Utils::ParameterAction::AlwaysEnabled, this);
621     cmd = am->registerAction(d->m_rebuildAction, Constants::REBUILD, globalcontext);
622     cmd->setAttribute(Core::Command::CA_UpdateText);
623     cmd->setDefaultText(d->m_rebuildAction->text());
624     mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
625
626     // deploy action
627     d->m_deployAction = new Utils::ParameterAction(tr("Deploy Project"), tr("Deploy Project \"%1\""),
628                                                      Utils::ParameterAction::AlwaysEnabled, this);
629     cmd = am->registerAction(d->m_deployAction, Constants::DEPLOY, globalcontext);
630     cmd->setAttribute(Core::Command::CA_UpdateText);
631     cmd->setDefaultText(d->m_deployAction->text());
632     mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
633
634     // Publish action
635     d->m_publishAction = new Utils::ParameterAction(tr("Publish Project..."), tr("Publish Project \"%1\"..."),
636                                                     Utils::ParameterAction::AlwaysEnabled, this);
637     cmd = am->registerAction(d->m_publishAction, Constants::PUBLISH, globalcontext);
638     cmd->setAttribute(Core::Command::CA_UpdateText);
639     cmd->setDefaultText(d->m_publishAction->text());
640     mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
641
642     // clean action
643     d->m_cleanAction = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""),
644                                                      Utils::ParameterAction::AlwaysEnabled, this);
645     cmd = am->registerAction(d->m_cleanAction, Constants::CLEAN, globalcontext);
646     cmd->setAttribute(Core::Command::CA_UpdateText);
647     cmd->setDefaultText(d->m_cleanAction->text());
648     mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
649
650     // build action (context menu)
651     d->m_buildActionContextMenu = new Utils::ParameterAction(tr("Build Project"), tr("Build Project \"%1\""),
652                                                              Utils::ParameterAction::AlwaysEnabled, this);
653     cmd = am->registerAction(d->m_buildActionContextMenu, Constants::BUILDCM, projecTreeContext);
654     cmd->setAttribute(Core::Command::CA_UpdateText);
655     cmd->setDefaultText(d->m_buildActionContextMenu->text());
656     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
657
658     // rebuild action (context menu)
659     d->m_rebuildActionContextMenu = new Utils::ParameterAction(tr("Rebuild Project"), tr("Rebuild Project \"%1\""),
660                                                                Utils::ParameterAction::AlwaysEnabled, this);
661     cmd = am->registerAction(d->m_rebuildActionContextMenu, Constants::REBUILDCM, projecTreeContext);
662     cmd->setAttribute(Core::Command::CA_UpdateText);
663     cmd->setDefaultText(d->m_rebuildActionContextMenu->text());
664     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
665
666     // deploy action (context menu)
667     d->m_deployActionContextMenu = new Utils::ParameterAction(tr("Deploy Project"), tr("Deploy Project \"%1\""),
668                                                               Utils::ParameterAction::AlwaysEnabled, this);
669     cmd = am->registerAction(d->m_deployActionContextMenu, Constants::DEPLOYCM, projecTreeContext);
670     cmd->setAttribute(Core::Command::CA_UpdateText);
671     cmd->setDefaultText(d->m_deployActionContextMenu->text());
672     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
673
674     // clean action (context menu)
675     d->m_cleanActionContextMenu = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""),
676                                                              Utils::ParameterAction::AlwaysEnabled, this);
677     cmd = am->registerAction(d->m_cleanActionContextMenu, Constants::CLEANCM, projecTreeContext);
678     cmd->setAttribute(Core::Command::CA_UpdateText);
679     cmd->setDefaultText(d->m_cleanActionContextMenu->text());
680     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
681
682     // build without dependencies action
683     d->m_buildProjectOnlyAction = new QAction(tr("Build Without Dependencies"), this);
684     cmd = am->registerAction(d->m_buildProjectOnlyAction, Constants::BUILDPROJECTONLY, globalcontext);
685
686     // rebuild without dependencies action
687     d->m_rebuildProjectOnlyAction = new QAction(tr("Rebuild Without Dependencies"), this);
688     cmd = am->registerAction(d->m_rebuildProjectOnlyAction, Constants::REBUILDPROJECTONLY, globalcontext);
689
690     // deploy without dependencies action
691     d->m_deployProjectOnlyAction = new QAction(tr("Deploy Without Dependencies"), this);
692     cmd = am->registerAction(d->m_deployProjectOnlyAction, Constants::DEPLOYPROJECTONLY, globalcontext);
693
694     // clean without dependencies action
695     d->m_cleanProjectOnlyAction = new QAction(tr("Clean Without Dependencies"), this);
696     cmd = am->registerAction(d->m_cleanProjectOnlyAction, Constants::CLEANPROJECTONLY, globalcontext);
697
698     // run action
699     QIcon runIcon(Constants::ICON_RUN);
700     runIcon.addFile(Constants::ICON_RUN_SMALL);
701     d->m_runAction = new QAction(runIcon, tr("Run"), this);
702     cmd = am->registerAction(d->m_runAction, Constants::RUN, globalcontext);
703     cmd->setAttribute(Core::Command::CA_UpdateText);
704
705     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+R")));
706     mbuild->addAction(cmd, Constants::G_BUILD_RUN);
707
708     modeManager->addAction(cmd, Constants::P_ACTION_RUN);
709
710     d->m_runActionContextMenu = new QAction(runIcon, tr("Run"), this);
711     cmd = am->registerAction(d->m_runActionContextMenu, Constants::RUNCONTEXTMENU, projecTreeContext);
712     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
713
714     // cancel build action
715     d->m_cancelBuildAction = new QAction(tr("Cancel Build"), this);
716     cmd = am->registerAction(d->m_cancelBuildAction, Constants::CANCELBUILD, globalcontext);
717     mbuild->addAction(cmd, Constants::G_BUILD_CANCEL);
718
719     // add new file action
720     d->m_addNewFileAction = new QAction(tr("Add New..."), this);
721     cmd = am->registerAction(d->m_addNewFileAction, ProjectExplorer::Constants::ADDNEWFILE,
722                        projecTreeContext);
723     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
724     msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
725     mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
726
727     // add existing file action
728     d->m_addExistingFilesAction = new QAction(tr("Add Existing Files..."), this);
729     cmd = am->registerAction(d->m_addExistingFilesAction, ProjectExplorer::Constants::ADDEXISTINGFILES,
730                        projecTreeContext);
731     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
732     msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
733     mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
734
735     // new subproject action
736     d->m_addNewSubprojectAction = new QAction(tr("New Subproject..."), this);
737     cmd = am->registerAction(d->m_addNewSubprojectAction, ProjectExplorer::Constants::ADDNEWSUBPROJECT,
738                        projecTreeContext);
739     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
740     msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
741
742     // unload project again, in right position
743     mprojectContextMenu->addAction(am->command(Constants::UNLOAD), Constants::G_PROJECT_FILES);
744
745     // remove file action
746     d->m_removeFileAction = new QAction(tr("Remove File..."), this);
747     cmd = am->registerAction(d->m_removeFileAction, ProjectExplorer::Constants::REMOVEFILE,
748                        projecTreeContext);
749     cmd->setDefaultKeySequence(QKeySequence::Delete);
750     mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
751
752     //: Remove project from parent profile (Project explorer view); will not physically delete any files.
753     d->m_removeProjectAction = new QAction(tr("Remove Project..."), this);
754     cmd = am->registerAction(d->m_removeProjectAction, ProjectExplorer::Constants::REMOVEPROJECT,
755                        projecTreeContext);
756     msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
757
758     // delete file action
759     d->m_deleteFileAction = new QAction(tr("Delete File..."), this);
760     cmd = am->registerAction(d->m_deleteFileAction, ProjectExplorer::Constants::DELETEFILE,
761                              projecTreeContext);
762     cmd->setDefaultKeySequence(QKeySequence::Delete);
763     mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
764
765     // renamefile action
766     d->m_renameFileAction = new QAction(tr("Rename"), this);
767     cmd = am->registerAction(d->m_renameFileAction, ProjectExplorer::Constants::RENAMEFILE,
768                        projecTreeContext);
769     mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
770     // Not yet used by anyone, so hide for now
771 //    mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
772 //    msubProject->addAction(cmd, Constants::G_FOLDER_FILES);
773 //    mproject->addAction(cmd, Constants::G_FOLDER_FILES);
774
775     // set startup project action
776     d->m_setStartupProjectAction = new QAction(tr("Set as Startup Project"), this);
777     cmd = am->registerAction(d->m_setStartupProjectAction, ProjectExplorer::Constants::SETSTARTUP,
778                              projecTreeContext);
779     mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FIRST);
780
781     // target selector
782     d->m_projectSelectorAction = new QAction(this);
783     d->m_projectSelectorAction->setCheckable(true);
784     d->m_projectSelectorAction->setEnabled(false);
785     QWidget *mainWindow = Core::ICore::instance()->mainWindow();
786     d->m_targetSelector = new Internal::MiniProjectTargetSelector(d->m_projectSelectorAction, mainWindow);
787     connect(d->m_projectSelectorAction, SIGNAL(triggered()), d->m_targetSelector, SLOT(show()));
788     modeManager->addProjectSelector(d->m_projectSelectorAction);
789
790     d->m_projectSelectorActionMenu = new QAction(this);
791     d->m_projectSelectorActionMenu->setEnabled(false);
792     d->m_projectSelectorActionMenu->setText(tr("Open Build/Run Target Selector..."));
793     connect(d->m_projectSelectorActionMenu, SIGNAL(triggered()), d->m_targetSelector, SLOT(show()));
794     cmd = am->registerAction(d->m_projectSelectorActionMenu, ProjectExplorer::Constants::SELECTTARGET,
795                        globalcontext);
796     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+T")));
797     mbuild->addAction(cmd, Constants::G_BUILD_RUN);
798
799     connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
800             d->m_targetSelector, SLOT(addProject(ProjectExplorer::Project*)));
801     connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)),
802             d->m_targetSelector, SLOT(removeProject(ProjectExplorer::Project*)));
803     connect(d->m_targetSelector, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
804             this, SLOT(setStartupProject(ProjectExplorer::Project*)));
805     connect(d->m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
806             d->m_targetSelector, SLOT(changeStartupProject(ProjectExplorer::Project*)));
807
808     connect(core, SIGNAL(saveSettingsRequested()),
809         this, SLOT(savePersistentSettings()));
810
811     addAutoReleasedObject(new ProjectTreeWidgetFactory);
812     addAutoReleasedObject(new FolderNavigationWidgetFactory);
813
814     if (QSettings *s = core->settings()) {
815         const QStringList fileNames = s->value("ProjectExplorer/RecentProjects/FileNames").toStringList();
816         const QStringList displayNames = s->value("ProjectExplorer/RecentProjects/DisplayNames").toStringList();
817         if (fileNames.size() == displayNames.size()) {
818             for (int i = 0; i < fileNames.size(); ++i) {
819                 if (QFileInfo(fileNames.at(i)).isFile())
820                     d->m_recentProjects.append(qMakePair(fileNames.at(i), displayNames.at(i)));
821             }
822         }
823     }
824
825     if (QSettings *s = core->settings()) {
826         d->m_projectExplorerSettings.buildBeforeDeploy = s->value("ProjectExplorer/Settings/BuildBeforeDeploy", true).toBool();
827         d->m_projectExplorerSettings.deployBeforeRun = s->value("ProjectExplorer/Settings/DeployBeforeRun", true).toBool();
828         d->m_projectExplorerSettings.saveBeforeBuild = s->value("ProjectExplorer/Settings/SaveBeforeBuild", false).toBool();
829         d->m_projectExplorerSettings.showCompilerOutput = s->value("ProjectExplorer/Settings/ShowCompilerOutput", false).toBool();
830         d->m_projectExplorerSettings.showRunOutput = s->value("ProjectExplorer/Settings/ShowRunOutput", true).toBool();
831         d->m_projectExplorerSettings.cleanOldAppOutput = s->value("ProjectExplorer/Settings/CleanOldAppOutput", false).toBool();
832         d->m_projectExplorerSettings.wrapAppOutput = s->value("ProjectExplorer/Settings/WrapAppOutput", true).toBool();
833         d->m_projectExplorerSettings.useJom = s->value("ProjectExplorer/Settings/UseJom", true).toBool();
834         d->m_projectExplorerSettings.autorestoreLastSession = s->value("ProjectExplorer/Settings/AutoRestoreLastSession", false).toBool();
835         d->m_projectExplorerSettings.environmentId = QUuid(s->value("ProjectExplorer/Settings/EnvironmentId").toString());
836         if (d->m_projectExplorerSettings.environmentId.isNull())
837             d->m_projectExplorerSettings.environmentId = QUuid::createUuid();
838     }
839
840     connect(d->m_sessionManagerAction, SIGNAL(triggered()), this, SLOT(showSessionManager()));
841     connect(d->m_newAction, SIGNAL(triggered()), this, SLOT(newProject()));
842     connect(d->m_loadAction, SIGNAL(triggered()), this, SLOT(loadAction()));
843     connect(d->m_buildProjectOnlyAction, SIGNAL(triggered()), this, SLOT(buildProjectOnly()));
844     connect(d->m_buildAction, SIGNAL(triggered()), this, SLOT(buildProject()));
845     connect(d->m_buildActionContextMenu, SIGNAL(triggered()), this, SLOT(buildProjectContextMenu()));
846     connect(d->m_buildSessionAction, SIGNAL(triggered()), this, SLOT(buildSession()));
847     connect(d->m_rebuildProjectOnlyAction, SIGNAL(triggered()), this, SLOT(rebuildProjectOnly()));
848     connect(d->m_rebuildAction, SIGNAL(triggered()), this, SLOT(rebuildProject()));
849     connect(d->m_rebuildActionContextMenu, SIGNAL(triggered()), this, SLOT(rebuildProjectContextMenu()));
850     connect(d->m_rebuildSessionAction, SIGNAL(triggered()), this, SLOT(rebuildSession()));
851     connect(d->m_deployProjectOnlyAction, SIGNAL(triggered()), this, SLOT(deployProjectOnly()));
852     connect(d->m_deployAction, SIGNAL(triggered()), this, SLOT(deployProject()));
853     connect(d->m_deployActionContextMenu, SIGNAL(triggered()), this, SLOT(deployProjectContextMenu()));
854     connect(d->m_deploySessionAction, SIGNAL(triggered()), this, SLOT(deploySession()));
855     connect(d->m_publishAction, SIGNAL(triggered()), this, SLOT(publishProject()));
856     connect(d->m_cleanProjectOnlyAction, SIGNAL(triggered()), this, SLOT(cleanProjectOnly()));
857     connect(d->m_cleanAction, SIGNAL(triggered()), this, SLOT(cleanProject()));
858     connect(d->m_cleanActionContextMenu, SIGNAL(triggered()), this, SLOT(cleanProjectContextMenu()));
859     connect(d->m_cleanSessionAction, SIGNAL(triggered()), this, SLOT(cleanSession()));
860     connect(d->m_runAction, SIGNAL(triggered()), this, SLOT(runProject()));
861     connect(d->m_runActionContextMenu, SIGNAL(triggered()), this, SLOT(runProjectContextMenu()));
862     connect(d->m_cancelBuildAction, SIGNAL(triggered()), this, SLOT(cancelBuild()));
863     connect(d->m_unloadAction, SIGNAL(triggered()), this, SLOT(unloadProject()));
864     connect(d->m_clearSession, SIGNAL(triggered()), this, SLOT(clearSession()));
865     connect(d->m_addNewFileAction, SIGNAL(triggered()), this, SLOT(addNewFile()));
866     connect(d->m_addExistingFilesAction, SIGNAL(triggered()), this, SLOT(addExistingFiles()));
867     connect(d->m_addNewSubprojectAction, SIGNAL(triggered()), this, SLOT(addNewSubproject()));
868     connect(d->m_removeProjectAction, SIGNAL(triggered()), this, SLOT(removeProject()));
869     connect(d->m_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
870     connect(d->m_showInGraphicalShell, SIGNAL(triggered()), this, SLOT(showInGraphicalShell()));
871     connect(d->m_openTerminalHere, SIGNAL(triggered()), this, SLOT(openTerminalHere()));
872     connect(d->m_removeFileAction, SIGNAL(triggered()), this, SLOT(removeFile()));
873     connect(d->m_deleteFileAction, SIGNAL(triggered()), this, SLOT(deleteFile()));
874     connect(d->m_renameFileAction, SIGNAL(triggered()), this, SLOT(renameFile()));
875     connect(d->m_setStartupProjectAction, SIGNAL(triggered()), this, SLOT(setStartupProject()));
876
877     connect(this, SIGNAL(updateRunActions()), this, SLOT(slotUpdateRunActions()));
878
879     updateActions();
880
881     connect(Core::ICore::instance(), SIGNAL(coreAboutToOpen()),
882             this, SLOT(determineSessionToRestoreAtStartup()));
883     connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(restoreSession()));
884
885     updateWelcomePage();
886
887     return true;
888 }
889
890 ProjectFileFactory *ProjectExplorerPlugin::findProjectFileFactory(const QString &filename) const
891 {
892     // Find factory
893     if (const Core::MimeType mt = Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(filename))) {
894         const QString mimeType = mt.type();
895         foreach (ProjectFileFactory *f, d->m_fileFactories)
896             if (f->mimeTypes().contains(mimeType))
897                 return f;
898     }
899     qWarning("Unable to find project file factory for '%s'", filename.toUtf8().constData());
900     return 0;
901 }
902
903 void ProjectExplorerPlugin::loadAction()
904 {
905     if (debug)
906         qDebug() << "ProjectExplorerPlugin::loadAction";
907
908
909     QString dir = d->m_lastOpenDirectory;
910
911     // for your special convenience, we preselect a pro file if it is
912     // the current file
913     if (Core::IEditor *editor = Core::EditorManager::instance()->currentEditor()) {
914         if (const Core::IFile *file = editor->file()) {
915             const QString fn = file->fileName();
916             const bool isProject = d->m_profileMimeTypes.contains(file->mimeType());
917             dir = isProject ? fn : QFileInfo(fn).absolutePath();
918         }
919     }
920
921     QString filename = QFileDialog::getOpenFileName(0, tr("Load Project"),
922                                                     dir,
923                                                     d->m_projectFilterString);
924     if (filename.isEmpty())
925         return;
926     if (ProjectFileFactory *pf = findProjectFileFactory(filename))
927         pf->open(filename);
928     updateActions();
929 }
930
931 void ProjectExplorerPlugin::unloadProject()
932 {
933     if (debug)
934         qDebug() << "ProjectExplorerPlugin::unloadProject";
935
936     Core::IFile *fi = d->m_currentProject->file();
937
938     if (!fi || fi->fileName().isEmpty()) //nothing to save?
939         return;
940
941     QList<Core::IFile*> filesToSave;
942     filesToSave << fi;
943
944     // check the number of modified files
945     int readonlycount = 0;
946     foreach (const Core::IFile *file, filesToSave) {
947         if (file->isReadOnly())
948             ++readonlycount;
949     }
950
951     bool success = false;
952     if (readonlycount > 0)
953         success = Core::ICore::instance()->fileManager()->saveModifiedFiles(filesToSave).isEmpty();
954     else
955         success = Core::ICore::instance()->fileManager()->saveModifiedFilesSilently(filesToSave).isEmpty();
956
957     if (!success)
958         return;
959
960     addToRecentProjects(fi->fileName(), d->m_currentProject->displayName());
961     d->m_session->removeProject(d->m_currentProject);
962     updateActions();
963 }
964
965 void ProjectExplorerPlugin::clearSession()
966 {
967     if (debug)
968         qDebug() << "ProjectExplorerPlugin::clearSession";
969
970     if (!d->m_session->clear())
971         return; // Action has been cancelled
972     updateActions();
973 }
974
975 void ProjectExplorerPlugin::extensionsInitialized()
976 {
977     d->m_fileFactories = ProjectFileFactory::createFactories(&d->m_projectFilterString);
978     foreach (ProjectFileFactory *pf, d->m_fileFactories) {
979         d->m_profileMimeTypes += pf->mimeTypes();
980         addAutoReleasedObject(pf);
981     }
982     d->m_buildManager->extensionsInitialized();
983 }
984
985 void ProjectExplorerPlugin::loadCustomWizards()
986 {
987     // Add custom wizards, for which other plugins might have registered
988     // class factories
989     static bool firstTime = true;
990     if (firstTime) {
991         firstTime = false;
992         foreach(Core::IWizard *cpw, ProjectExplorer::CustomWizard::createWizards())
993             addAutoReleasedObject(cpw);
994     }
995 }
996
997 ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown()
998 {
999     d->m_proWindow->aboutToShutdown(); // disconnect from session
1000     d->m_session->clear();
1001     d->m_projectsMode = 0;
1002     // Attempt to synchronously shutdown all run controls.
1003     // If that fails, fall back to asynchronous shutdown (Debugger run controls
1004     // might shutdown asynchronously).
1005     if (d->m_outputPane->closeTabs(false /* No prompt any more */))
1006         return SynchronousShutdown;
1007     connect(d->m_outputPane, SIGNAL(allRunControlsFinished()),
1008             this, SIGNAL(asynchronousShutdownFinished()));
1009     return AsynchronousShutdown;
1010 }
1011
1012 void ProjectExplorerPlugin::newProject()
1013 {
1014     if (debug)
1015         qDebug() << "ProjectExplorerPlugin::newProject";
1016
1017     Core::ICore::instance()->showNewItemDialog(tr("New Project", "Title of dialog"),
1018                               Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard));
1019     updateActions();
1020 }
1021
1022 void ProjectExplorerPlugin::showSessionManager()
1023 {
1024     if (debug)
1025         qDebug() << "ProjectExplorerPlugin::showSessionManager";
1026
1027     if (d->m_session->isDefaultVirgin()) {
1028         // do not save new virgin default sessions
1029     } else {
1030         d->m_session->save();
1031     }
1032     SessionDialog sessionDialog(d->m_session);
1033     sessionDialog.setAutoLoadSession(d->m_projectExplorerSettings.autorestoreLastSession);
1034     sessionDialog.exec();
1035     d->m_projectExplorerSettings.autorestoreLastSession = sessionDialog.autoLoadSession();
1036
1037     updateActions();
1038
1039     Core::ModeManager *modeManager = Core::ModeManager::instance();
1040     Core::IMode *welcomeMode = modeManager->mode(Core::Constants::MODE_WELCOME);
1041     if (modeManager->currentMode() == welcomeMode)
1042         updateWelcomePage();
1043 }
1044
1045 void ProjectExplorerPlugin::setStartupProject(Project *project)
1046 {
1047     if (debug)
1048         qDebug() << "ProjectExplorerPlugin::setStartupProject";
1049
1050     if (!project)
1051         return;
1052     d->m_session->setStartupProject(project);
1053     updateActions();
1054 }
1055
1056 void ProjectExplorerPlugin::publishProject()
1057 {
1058     const Project * const project = d->m_session->startupProject();
1059     QTC_ASSERT(project, return);
1060     PublishingWizardSelectionDialog selectionDialog(project);
1061     if (selectionDialog.exec() == QDialog::Accepted) {
1062         QWizard * const publishingWizard
1063             = selectionDialog.createSelectedWizard();
1064         publishingWizard->exec();
1065         delete publishingWizard;
1066     }
1067 }
1068
1069 void ProjectExplorerPlugin::savePersistentSettings()
1070 {
1071     if (debug)
1072         qDebug()<<"ProjectExplorerPlugin::savePersistentSettings()";
1073
1074     foreach (Project *pro, d->m_session->projects())
1075         pro->saveSettings();
1076
1077     if (d->m_session->isDefaultVirgin()) {
1078         // do not save new virgin default sessions
1079     } else {
1080         d->m_session->save();
1081     }
1082
1083     QSettings *s = Core::ICore::instance()->settings();
1084     if (s) {
1085         s->setValue("ProjectExplorer/StartupSession", d->m_session->currentSession());
1086         s->remove("ProjectExplorer/RecentProjects/Files");
1087
1088         QStringList fileNames;
1089         QStringList displayNames;
1090         QList<QPair<QString, QString> >::const_iterator it, end;
1091         end = d->m_recentProjects.constEnd();
1092         for (it = d->m_recentProjects.constBegin(); it != end; ++it) {
1093             fileNames << (*it).first;
1094             displayNames << (*it).second;
1095         }
1096
1097         s->setValue("ProjectExplorer/RecentProjects/FileNames", fileNames);
1098         s->setValue("ProjectExplorer/RecentProjects/DisplayNames", displayNames);
1099
1100         s->setValue("ProjectExplorer/Settings/BuildBeforeDeploy", d->m_projectExplorerSettings.buildBeforeDeploy);
1101         s->setValue("ProjectExplorer/Settings/DeployBeforeRun", d->m_projectExplorerSettings.deployBeforeRun);
1102         s->setValue("ProjectExplorer/Settings/SaveBeforeBuild", d->m_projectExplorerSettings.saveBeforeBuild);
1103         s->setValue("ProjectExplorer/Settings/ShowCompilerOutput", d->m_projectExplorerSettings.showCompilerOutput);
1104         s->setValue("ProjectExplorer/Settings/ShowRunOutput", d->m_projectExplorerSettings.showRunOutput);
1105         s->setValue("ProjectExplorer/Settings/CleanOldAppOutput", d->m_projectExplorerSettings.cleanOldAppOutput);
1106         s->setValue("ProjectExplorer/Settings/WrapAppOutput", d->m_projectExplorerSettings.wrapAppOutput);
1107         s->setValue("ProjectExplorer/Settings/UseJom", d->m_projectExplorerSettings.useJom);
1108         s->setValue("ProjectExplorer/Settings/AutoRestoreLastSession", d->m_projectExplorerSettings.autorestoreLastSession);
1109         s->setValue("ProjectExplorer/Settings/EnvironmentId", d->m_projectExplorerSettings.environmentId.toString());
1110     }
1111 }
1112
1113 bool ProjectExplorerPlugin::openProject(const QString &fileName)
1114 {
1115     if (debug)
1116         qDebug() << "ProjectExplorerPlugin::openProject";
1117
1118     QList<Project *> list = openProjects(QStringList() << fileName);
1119     if (!list.isEmpty()) {
1120         addToRecentProjects(fileName, list.first()->displayName());
1121         return true;
1122     }
1123     return false;
1124 }
1125
1126 static inline QList<IProjectManager*> allProjectManagers()
1127 {
1128     ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
1129     return pm->getObjects<IProjectManager>();
1130 }
1131
1132 QList<Project *> ProjectExplorerPlugin::openProjects(const QStringList &fileNames)
1133 {
1134     if (debug)
1135         qDebug() << "ProjectExplorerPlugin - opening projects " << fileNames;
1136
1137     const QList<IProjectManager*> projectManagers = allProjectManagers();
1138
1139     QList<Project*> openedPro;
1140     foreach (const QString &fileName, fileNames) {
1141         if (const Core::MimeType mt = Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName))) {
1142             foreach (IProjectManager *manager, projectManagers) {
1143                 if (manager->mimeType() == mt.type()) {
1144                     if (Project *pro = manager->openProject(fileName)) {
1145                         if (pro->restoreSettings()) {
1146                             connect(pro, SIGNAL(fileListChanged()), this, SIGNAL(fileListChanged()));
1147                             d->m_session->addProject(pro);
1148                             // Make sure we always have a current project / node
1149                             if (!d->m_currentProject && !openedPro.isEmpty())
1150                                 setCurrentNode(pro->rootProjectNode());
1151                             openedPro += pro;
1152                         } else {
1153                             delete pro;
1154                         }
1155                     }
1156                     d->m_session->reportProjectLoadingProgress();
1157                     break;
1158                 }
1159             }
1160         }
1161     }
1162     updateActions();
1163
1164     if (openedPro.isEmpty()) {
1165         qDebug() << "ProjectExplorerPlugin - Could not open any projects!";
1166     } else {
1167         Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
1168     }
1169
1170     return openedPro;
1171 }
1172
1173 Project *ProjectExplorerPlugin::currentProject() const
1174 {
1175     if (debug) {
1176         if (d->m_currentProject)
1177             qDebug() << "ProjectExplorerPlugin::currentProject returns " << d->m_currentProject->displayName();
1178         else
1179             qDebug() << "ProjectExplorerPlugin::currentProject returns 0";
1180     }
1181     return d->m_currentProject;
1182 }
1183
1184 Node *ProjectExplorerPlugin::currentNode() const
1185 {
1186     return d->m_currentNode;
1187 }
1188
1189 void ProjectExplorerPlugin::setCurrentFile(Project *project, const QString &filePath)
1190 {
1191     setCurrent(project, filePath, 0);
1192 }
1193
1194 void ProjectExplorerPlugin::setCurrentFile(const QString &filePath)
1195 {
1196     Project *project = d->m_session->projectForFile(filePath);
1197     // If the file is not in any project, stay with the current project
1198     // e.g. on opening a git diff buffer, git log buffer, we don't change the project
1199     // I'm not 100% sure this is correct
1200     if (!project)
1201         project = d->m_currentProject;
1202     setCurrent(project, filePath, 0);
1203 }
1204
1205 void ProjectExplorerPlugin::setCurrentNode(Node *node)
1206 {
1207     setCurrent(d->m_session->projectForNode(node), QString(), node);
1208 }
1209
1210 SessionManager *ProjectExplorerPlugin::session() const
1211 {
1212     return d->m_session;
1213 }
1214
1215 Project *ProjectExplorerPlugin::startupProject() const
1216 {
1217     if (debug)
1218         qDebug() << "ProjectExplorerPlugin::startupProject";
1219
1220     return d->m_session->startupProject();
1221 }
1222
1223 void ProjectExplorerPlugin::updateWelcomePage()
1224 {
1225     ProjectWelcomePageWidget::WelcomePageData welcomePageData;
1226     welcomePageData.sessionList =  d->m_session->sessions();
1227     welcomePageData.activeSession = d->m_session->activeSession();
1228     welcomePageData.previousSession = d->m_session->lastSession();
1229     welcomePageData.projectList = d->m_recentProjects;
1230     d->m_welcomePage->setWelcomePageData(welcomePageData);
1231 }
1232
1233 void ProjectExplorerPlugin::currentModeChanged(Core::IMode *mode, Core::IMode *oldMode)
1234 {
1235     if (mode && mode->id() == Core::Id(Core::Constants::MODE_WELCOME))
1236         updateWelcomePage();
1237     if (oldMode == d->m_projectsMode)
1238         savePersistentSettings();
1239 }
1240
1241 void ProjectExplorerPlugin::determineSessionToRestoreAtStartup()
1242 {
1243     QStringList arguments = ExtensionSystem::PluginManager::instance()->arguments();
1244     if (arguments.contains("-lastsession")
1245             || d->m_projectExplorerSettings.autorestoreLastSession) {
1246         d->m_sessionToRestoreAtStartup = d->m_session->lastSession();
1247     } else {
1248         QStringList sessions = d->m_session->sessions();
1249         // We have command line arguments, try to find a session in them
1250         // Default to no session loading
1251         foreach (const QString &arg, arguments) {
1252             if (sessions.contains(arg)) {
1253                 // Session argument
1254                 d->m_sessionToRestoreAtStartup = arg;
1255                 break;
1256             }
1257         }
1258     }
1259
1260     if (!d->m_sessionToRestoreAtStartup.isNull())
1261         Core::ICore::instance()->modeManager()->activateMode(Core::Constants::MODE_EDIT);
1262 }
1263
1264 /*!
1265     \fn void ProjectExplorerPlugin::restoreSession()
1266
1267     This method is connected to the ICore::coreOpened signal.  If
1268     there was no session explicitly loaded, it creates an empty new
1269     default session and puts the list of recent projects and sessions
1270     onto the welcome page.
1271 */
1272 void ProjectExplorerPlugin::restoreSession()
1273 {
1274     if (debug)
1275         qDebug() << "ProjectExplorerPlugin::restoreSession";
1276
1277     // We have command line arguments, try to find a session in them
1278     QStringList arguments = ExtensionSystem::PluginManager::instance()->arguments();
1279     arguments.removeOne(d->m_sessionToRestoreAtStartup);
1280
1281     // Restore latest session or what was passed on the command line
1282     if (d->m_sessionToRestoreAtStartup.isEmpty()) {
1283         d->m_session->createAndLoadNewDefaultSession();
1284     } else {
1285         d->m_session->loadSession(d->m_sessionToRestoreAtStartup);
1286     }
1287
1288     // update welcome page
1289     Core::ModeManager *modeManager = Core::ModeManager::instance();
1290     connect(modeManager, SIGNAL(currentModeChanged(Core::IMode*, Core::IMode*)),
1291             this, SLOT(currentModeChanged(Core::IMode*, Core::IMode*)));
1292     connect(d->m_welcomePage, SIGNAL(requestSession(QString)), this, SLOT(loadSession(QString)));
1293     connect(d->m_welcomePage, SIGNAL(requestProject(QString)), this, SLOT(loadProject(QString)));
1294
1295     QStringList combinedList;
1296     // Converts "filename" "+45" or "filename" ":23"
1297     // into     "filename+45"   and "filename:23"
1298     foreach (const QString &str, arguments) {
1299         if (!combinedList.isEmpty() && (str.startsWith("+") || str.startsWith(":"))) {
1300             combinedList.last().append(str);
1301         } else {
1302             combinedList << str;
1303         }
1304     }
1305
1306     Core::ICore::instance()->openFiles(combinedList, Core::ICore::OpenFilesFlags(Core::ICore::CanContainLineNumbers | Core::ICore::SwitchMode));
1307     updateActions();
1308
1309 }
1310
1311 void ProjectExplorerPlugin::loadSession(const QString &session)
1312 {
1313     if (debug)
1314         qDebug() << "ProjectExplorerPlugin::loadSession" << session;
1315     d->m_session->loadSession(session);
1316 }
1317
1318
1319 void ProjectExplorerPlugin::showContextMenu(const QPoint &globalPos, Node *node)
1320 {
1321     QMenu *contextMenu = 0;
1322
1323     if (!node)
1324         node = d->m_session->sessionNode();
1325
1326     if (node->nodeType() != SessionNodeType) {
1327         Project *project = d->m_session->projectForNode(node);
1328         setCurrentNode(node);
1329
1330         emit aboutToShowContextMenu(project, node);
1331         switch (node->nodeType()) {
1332         case ProjectNodeType:
1333             if (node->parentFolderNode() == d->m_session->sessionNode())
1334                 contextMenu = d->m_projectMenu;
1335             else
1336                 contextMenu = d->m_subProjectMenu;
1337             break;
1338         case FolderNodeType:
1339             contextMenu = d->m_folderMenu;
1340             break;
1341         case FileNodeType:
1342             populateOpenWithMenu();
1343             contextMenu = d->m_fileMenu;
1344             break;
1345         default:
1346             qWarning("ProjectExplorerPlugin::showContextMenu - Missing handler for node type");
1347         }
1348     } else { // session item
1349         emit aboutToShowContextMenu(0, node);
1350
1351         contextMenu = d->m_sessionContextMenu;
1352     }
1353
1354     updateContextMenuActions();
1355     if (contextMenu && contextMenu->actions().count() > 0) {
1356         contextMenu->popup(globalPos);
1357     }
1358 }
1359
1360 BuildManager *ProjectExplorerPlugin::buildManager() const
1361 {
1362     return d->m_buildManager;
1363 }
1364
1365 void ProjectExplorerPlugin::buildStateChanged(Project * pro)
1366 {
1367     if (debug) {
1368         qDebug() << "buildStateChanged";
1369         qDebug() << pro->file()->fileName() << "isBuilding()" << d->m_buildManager->isBuilding(pro);
1370     }
1371     Q_UNUSED(pro)
1372     updateActions();
1373 }
1374
1375 void ProjectExplorerPlugin::executeRunConfiguration(RunConfiguration *runConfiguration, const QString &runMode)
1376 {
1377     if (IRunControlFactory *runControlFactory = findRunControlFactory(runConfiguration, runMode)) {
1378         emit aboutToExecuteProject(runConfiguration->target()->project(), runMode);
1379
1380         RunControl *control = runControlFactory->create(runConfiguration, runMode);
1381         if (!control)
1382             return;
1383         startRunControl(control, runMode);
1384     }
1385 }
1386
1387 void ProjectExplorerPlugin::startRunControl(RunControl *runControl, const QString &runMode)
1388 {
1389     d->m_outputPane->createNewOutputWindow(runControl);
1390     if (runMode == ProjectExplorer::Constants::RUNMODE && d->m_projectExplorerSettings.showRunOutput)
1391         d->m_outputPane->popup(false);
1392     d->m_outputPane->showTabFor(runControl);
1393     connect(runControl, SIGNAL(finished()), this, SLOT(runControlFinished()));
1394     runControl->start();
1395     emit updateRunActions();
1396 }
1397
1398 void ProjectExplorerPlugin::buildQueueFinished(bool success)
1399 {
1400     if (debug)
1401         qDebug() << "buildQueueFinished()" << success;
1402
1403     updateActions();
1404
1405     if (success && d->m_delayedRunConfiguration) {
1406         executeRunConfiguration(d->m_delayedRunConfiguration, d->m_runMode);
1407     } else {
1408         if (d->m_buildManager->tasksAvailable())
1409             d->m_buildManager->showTaskWindow();
1410     }
1411     d->m_delayedRunConfiguration = 0;
1412     d->m_runMode.clear();
1413 }
1414
1415 void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node *node)
1416 {
1417     if (debug)
1418         qDebug() << "ProjectExplorer - setting path to " << (node ? node->path() : filePath)
1419                 << " and project to " << (project ? project->displayName() : "0");
1420
1421     if (node)
1422         filePath = node->path();
1423     else
1424         node = d->m_session->nodeForFile(filePath, project);
1425
1426     Core::ICore *core = Core::ICore::instance();
1427
1428     bool projectChanged = false;
1429     if (d->m_currentProject != project) {
1430         Core::Context oldContext;
1431         Core::Context newContext;
1432
1433         if (d->m_currentProject) {
1434             oldContext.add(d->m_currentProject->projectManager()->projectContext());
1435             oldContext.add(d->m_currentProject->projectManager()->projectLanguage());
1436         }
1437         if (project) {
1438             newContext.add(project->projectManager()->projectContext());
1439             newContext.add(project->projectManager()->projectLanguage());
1440         }
1441
1442         core->updateAdditionalContexts(oldContext, newContext);
1443
1444         d->m_currentProject = project;
1445
1446         projectChanged = true;
1447     }
1448
1449     if (projectChanged || d->m_currentNode != node) {
1450         d->m_currentNode = node;
1451         if (debug)
1452             qDebug() << "ProjectExplorer - currentNodeChanged(" << (node ? node->path() : "0") << ", " << (project ? project->displayName() : "0") << ")";
1453         emit currentNodeChanged(d->m_currentNode, project);
1454         updateContextMenuActions();
1455     }
1456     if (projectChanged) {
1457         if (debug)
1458             qDebug() << "ProjectExplorer - currentProjectChanged(" << (project ? project->displayName() : "0") << ")";
1459         emit currentProjectChanged(project);
1460         updateActions();
1461     }
1462
1463     core->fileManager()->setCurrentFile(filePath);
1464 }
1465
1466 void ProjectExplorerPlugin::updateActions()
1467 {
1468     if (debug)
1469         qDebug() << "ProjectExplorerPlugin::updateActions";
1470
1471     Project *project = startupProject();
1472     bool enableBuildActions = project
1473                               && ! (d->m_buildManager->isBuilding(project))
1474                               && hasBuildSettings(project);
1475
1476     bool enableBuildActionsContextMenu = d->m_currentProject
1477                               && ! (d->m_buildManager->isBuilding(d->m_currentProject))
1478                               && hasBuildSettings(d->m_currentProject);
1479
1480     bool hasProjects = !d->m_session->projects().isEmpty();
1481     bool building = d->m_buildManager->isBuilding();
1482     QString projectName = project ? project->displayName() : QString();
1483     QString projectNameContextMenu = d->m_currentProject ? d->m_currentProject->displayName() : QString();
1484
1485     if (debug)
1486         qDebug() << "BuildManager::isBuilding()" << building;
1487
1488     d->m_unloadAction->setParameter(projectNameContextMenu);
1489
1490     d->m_buildAction->setParameter(projectName);
1491     d->m_rebuildAction->setParameter(projectName);
1492     d->m_cleanAction->setParameter(projectName);
1493
1494     d->m_buildAction->setEnabled(enableBuildActions);
1495     d->m_rebuildAction->setEnabled(enableBuildActions);
1496     d->m_cleanAction->setEnabled(enableBuildActions);
1497
1498     d->m_buildActionContextMenu->setParameter(projectNameContextMenu);
1499     d->m_rebuildActionContextMenu->setParameter(projectNameContextMenu);
1500     d->m_cleanActionContextMenu->setParameter(projectNameContextMenu);
1501
1502     d->m_buildActionContextMenu->setEnabled(enableBuildActionsContextMenu);
1503     d->m_rebuildActionContextMenu->setEnabled(enableBuildActionsContextMenu);
1504     d->m_cleanActionContextMenu->setEnabled(enableBuildActionsContextMenu);
1505
1506     d->m_buildProjectOnlyAction->setEnabled(enableBuildActions);
1507     d->m_rebuildProjectOnlyAction->setEnabled(enableBuildActions);
1508     d->m_cleanProjectOnlyAction->setEnabled(enableBuildActions);
1509
1510     d->m_clearSession->setEnabled(hasProjects && !building);
1511     d->m_buildSessionAction->setEnabled(hasProjects && !building);
1512     d->m_rebuildSessionAction->setEnabled(hasProjects && !building);
1513     d->m_cleanSessionAction->setEnabled(hasProjects && !building);
1514     d->m_cancelBuildAction->setEnabled(building);
1515
1516     d->m_publishAction->setEnabled(hasProjects);
1517
1518     d->m_projectSelectorAction->setEnabled(!session()->projects().isEmpty());
1519     d->m_projectSelectorActionMenu->setEnabled(!session()->projects().isEmpty());
1520
1521     updateDeployActions();
1522 }
1523
1524 // NBS TODO check projectOrder()
1525 // what we want here is all the projects pro depends on
1526 QStringList ProjectExplorerPlugin::allFilesWithDependencies(Project *pro)
1527 {
1528     if (debug)
1529         qDebug() << "ProjectExplorerPlugin::allFilesWithDependencies(" << pro->file()->fileName() << ")";
1530
1531     QStringList filesToSave;
1532     foreach (Project *p, d->m_session->projectOrder(pro)) {
1533         FindAllFilesVisitor filesVisitor;
1534         p->rootProjectNode()->accept(&filesVisitor);
1535         filesToSave << filesVisitor.filePaths();
1536     }
1537     qSort(filesToSave);
1538     return filesToSave;
1539 }
1540
1541 bool ProjectExplorerPlugin::saveModifiedFiles()
1542 {
1543     if (debug)
1544         qDebug() << "ProjectExplorerPlugin::saveModifiedFiles";
1545
1546     QList<Core::IFile *> filesToSave = Core::ICore::instance()->fileManager()->modifiedFiles();
1547     if (!filesToSave.isEmpty()) {
1548         if (d->m_projectExplorerSettings.saveBeforeBuild) {
1549             Core::ICore::instance()->fileManager()->saveModifiedFilesSilently(filesToSave);
1550         } else {
1551             bool cancelled = false;
1552             bool alwaysSave = false;
1553
1554             Core::FileManager *fm = Core::ICore::instance()->fileManager();
1555             fm->saveModifiedFiles(filesToSave, &cancelled, QString(),
1556                                   tr("Always save files before build"), &alwaysSave);
1557
1558             if (cancelled)
1559                 return false;
1560             if (alwaysSave)
1561                 d->m_projectExplorerSettings.saveBeforeBuild = true;
1562         }
1563     }
1564     return true;
1565 }
1566
1567 //NBS handle case where there is no activeBuildConfiguration
1568 // because someone delete all build configurations
1569
1570 void ProjectExplorerPlugin::deploy(QList<Project *> projects)
1571 {
1572     QStringList steps;
1573     if (d->m_projectExplorerSettings.buildBeforeDeploy)
1574         steps << Constants::BUILDSTEPS_BUILD;
1575     steps << Constants::BUILDSTEPS_DEPLOY;
1576     queue(projects, steps);
1577 }
1578
1579 int ProjectExplorerPlugin::queue(QList<Project *> projects, QStringList stepIds)
1580 {
1581     if (debug) {
1582         QStringList projectNames;
1583         foreach (Project *p, projects)
1584             projectNames << p->displayName();
1585         qDebug() << "Building" << stepIds << "for projects" << projectNames;
1586     }
1587
1588     if (!saveModifiedFiles())
1589         return -1;
1590
1591     QList<BuildStepList *> stepLists;
1592     foreach (Project *pro, projects) {
1593         if (!pro || !pro->activeTarget())
1594             continue;
1595         foreach (const QString id, stepIds) {
1596             BuildStepList *bsl = 0;
1597             if (id == Core::Id(Constants::BUILDSTEPS_DEPLOY)
1598                 && pro->activeTarget()->activeDeployConfiguration())
1599                 bsl = pro->activeTarget()->activeDeployConfiguration()->stepList();
1600             else if (pro->activeTarget()->activeBuildConfiguration())
1601                 bsl = pro->activeTarget()->activeBuildConfiguration()->stepList(id);
1602
1603             if (!bsl || bsl->isEmpty())
1604                 continue;
1605             stepLists << bsl;
1606         }
1607     }
1608
1609     if (stepLists.isEmpty())
1610         return 0;
1611     if (!d->m_buildManager->buildLists(stepLists))
1612         return -1;
1613     return stepLists.count();
1614 }
1615
1616 void ProjectExplorerPlugin::buildProjectOnly()
1617 {
1618     queue(QList<Project *>() << session()->startupProject(), QStringList() << Constants::BUILDSTEPS_BUILD);
1619 }
1620
1621 void ProjectExplorerPlugin::buildProject()
1622 {
1623     queue(d->m_session->projectOrder(session()->startupProject()),
1624           QStringList() << Constants::BUILDSTEPS_BUILD);
1625 }
1626
1627 void ProjectExplorerPlugin::buildProjectContextMenu()
1628 {
1629     queue(d->m_session->projectOrder(d->m_currentProject),
1630           QStringList() << Constants::BUILDSTEPS_BUILD);
1631 }
1632
1633 void ProjectExplorerPlugin::buildSession()
1634 {
1635     queue(d->m_session->projectOrder(),
1636           QStringList() << Constants::BUILDSTEPS_BUILD);
1637 }
1638
1639 void ProjectExplorerPlugin::rebuildProjectOnly()
1640 {
1641     queue(QList<Project *>() << session()->startupProject(),
1642           QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_BUILD);
1643 }
1644
1645 void ProjectExplorerPlugin::rebuildProject()
1646 {
1647     queue(d->m_session->projectOrder(session()->startupProject()),
1648           QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_BUILD);
1649 }
1650
1651 void ProjectExplorerPlugin::rebuildProjectContextMenu()
1652 {
1653     queue(d->m_session->projectOrder(d->m_currentProject),
1654           QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_BUILD);
1655 }
1656
1657 void ProjectExplorerPlugin::rebuildSession()
1658 {
1659     queue(d->m_session->projectOrder(),
1660           QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_BUILD);
1661 }
1662
1663 void ProjectExplorerPlugin::deployProjectOnly()
1664 {
1665     deploy(QList<Project *>() << session()->startupProject());
1666 }
1667
1668 void ProjectExplorerPlugin::deployProject()
1669 {
1670     deploy(d->m_session->projectOrder(session()->startupProject()));
1671 }
1672
1673 void ProjectExplorerPlugin::deployProjectContextMenu()
1674 {
1675     deploy(d->m_session->projectOrder(d->m_currentProject));
1676 }
1677
1678 void ProjectExplorerPlugin::deploySession()
1679 {
1680     deploy(d->m_session->projectOrder());
1681 }
1682
1683 void ProjectExplorerPlugin::cleanProjectOnly()
1684 {
1685     queue(QList<Project *>() << session()->startupProject(),
1686           QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_CLEAN);
1687 }
1688
1689 void ProjectExplorerPlugin::cleanProject()
1690 {
1691     queue(d->m_session->projectOrder(session()->startupProject()),
1692           QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_CLEAN);
1693 }
1694
1695 void ProjectExplorerPlugin::cleanProjectContextMenu()
1696 {
1697     queue(d->m_session->projectOrder(d->m_currentProject),
1698           QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_CLEAN);
1699 }
1700
1701 void ProjectExplorerPlugin::cleanSession()
1702 {
1703     queue(d->m_session->projectOrder(),
1704           QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_CLEAN);
1705 }
1706
1707 void ProjectExplorerPlugin::runProject()
1708 {
1709     runProject(startupProject(), ProjectExplorer::Constants::RUNMODE);
1710 }
1711
1712 void ProjectExplorerPlugin::runProjectContextMenu()
1713 {
1714     runProject(d->m_currentProject, ProjectExplorer::Constants::RUNMODE);
1715 }
1716
1717 bool ProjectExplorerPlugin::hasBuildSettings(Project *pro)
1718 {
1719     const QList<Project *> & projects = d->m_session->projectOrder(pro);
1720     foreach(Project *project, projects)
1721         if (project->activeTarget()->activeBuildConfiguration())
1722             return true;
1723     return false;
1724 }
1725
1726 bool ProjectExplorerPlugin::coreAboutToClose()
1727 {
1728     if (d->m_buildManager->isBuilding()) {
1729         QMessageBox box;
1730         QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Close"), QMessageBox::AcceptRole);
1731         QPushButton *cancelClose = box.addButton(tr("Do Not Close"), QMessageBox::RejectRole);
1732         box.setDefaultButton(cancelClose);
1733         box.setWindowTitle(tr("Close Qt Creator?"));
1734         box.setText(tr("A project is currently being built."));
1735         box.setInformativeText(tr("Do you want to cancel the build process and close Qt Creator anyway?"));
1736         box.exec();
1737         if (box.clickedButton() != closeAnyway)
1738             return false;
1739     }
1740     if (!d->m_outputPane->aboutToClose())
1741         return false;
1742     return true;
1743 }
1744
1745 bool ProjectExplorerPlugin::hasDeploySettings(Project *pro)
1746 {
1747     const QList<Project *> & projects = d->m_session->projectOrder(pro);
1748     foreach(Project *project, projects)
1749         if (project->activeTarget()->activeDeployConfiguration() &&
1750                 !project->activeTarget()->activeDeployConfiguration()->stepList()->isEmpty())
1751             return true;
1752     return false;
1753 }
1754
1755 void ProjectExplorerPlugin::runProject(Project *pro, QString mode)
1756 {
1757     if (!pro)
1758         return;
1759
1760     if (!pro->activeTarget()->activeRunConfiguration()->isEnabled())
1761         return;
1762
1763     QStringList stepIds;
1764     if (d->m_projectExplorerSettings.deployBeforeRun) {
1765         if (d->m_projectExplorerSettings.buildBeforeDeploy)
1766             stepIds << Constants::BUILDSTEPS_BUILD;
1767         stepIds << Constants::BUILDSTEPS_DEPLOY;
1768     }
1769     const QList<Project *> &projects = d->m_session->projectOrder(pro);
1770     int queueCount = queue(projects, stepIds);
1771
1772     if (queueCount < 0) // something went wrong
1773         return;
1774
1775     if (queueCount > 0) {
1776         // delay running till after our queued steps were processed
1777         d->m_runMode = mode;
1778         d->m_delayedRunConfiguration = pro->activeTarget()->activeRunConfiguration();
1779     } else {
1780         executeRunConfiguration(pro->activeTarget()->activeRunConfiguration(), mode);
1781     }
1782     emit updateRunActions();
1783 }
1784
1785 void ProjectExplorerPlugin::runControlFinished()
1786 {
1787     emit updateRunActions();
1788 }
1789
1790 void ProjectExplorerPlugin::startupProjectChanged()
1791 {
1792     static QPointer<Project> previousStartupProject = 0;
1793     Project *project = startupProject();
1794     if (project == previousStartupProject)
1795         return;
1796
1797     if (d->m_projectsMode)
1798         d->m_projectsMode->setEnabled(project);
1799
1800     if (previousStartupProject) {
1801         disconnect(previousStartupProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
1802                    this, SLOT(activeTargetChanged()));
1803     }
1804
1805     previousStartupProject = project;
1806
1807     if (project) {
1808         connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
1809                 this, SLOT(activeTargetChanged()));
1810     }
1811
1812     activeTargetChanged();
1813
1814     emit updateRunActions();
1815 }
1816
1817 void ProjectExplorerPlugin::activeTargetChanged()
1818 {
1819     static QPointer<Target> previousTarget = 0;
1820     Target *target = 0;
1821     if (startupProject())
1822         target = startupProject()->activeTarget();
1823     if (target == previousTarget)
1824         return;
1825
1826     if (previousTarget) {
1827         disconnect(previousTarget, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
1828                    this, SLOT(activeRunConfigurationChanged()));
1829     }
1830     previousTarget = target;
1831     if (target) {
1832         connect(target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
1833                 this, SLOT(activeRunConfigurationChanged()));
1834     }
1835
1836     updateDeployActions();
1837     activeRunConfigurationChanged();
1838 }
1839
1840 void ProjectExplorerPlugin::activeRunConfigurationChanged()
1841 {
1842     static QPointer<RunConfiguration> previousRunConfiguration = 0;
1843     RunConfiguration *rc = 0;
1844     if (startupProject() && startupProject()->activeTarget())
1845         rc = startupProject()->activeTarget()->activeRunConfiguration();
1846     if (rc == previousRunConfiguration)
1847         return;
1848     if (previousRunConfiguration) {
1849         disconnect(previousRunConfiguration, SIGNAL(isEnabledChanged(bool)),
1850                    this, SIGNAL(updateRunActions()));
1851     }
1852     previousRunConfiguration = rc;
1853     if (rc) {
1854         connect(rc, SIGNAL(isEnabledChanged(bool)),
1855                 this, SIGNAL(updateRunActions()));
1856     }
1857     emit updateRunActions();
1858 }
1859
1860 // NBS TODO implement more than one runner
1861 IRunControlFactory *ProjectExplorerPlugin::findRunControlFactory(RunConfiguration *config, const QString &mode)
1862 {
1863     ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
1864     const QList<IRunControlFactory *> factories = pm->getObjects<IRunControlFactory>();
1865     foreach (IRunControlFactory *f, factories)
1866         if (f->canRun(config, mode))
1867             return f;
1868     return 0;
1869 }
1870
1871 void ProjectExplorerPlugin::updateDeployActions()
1872 {
1873     Project *project = startupProject();
1874
1875     bool enableDeployActions = project
1876             && ! (d->m_buildManager->isBuilding(project))
1877             && hasDeploySettings(project);
1878     bool enableDeployActionsContextMenu = d->m_currentProject
1879                               && ! (d->m_buildManager->isBuilding(d->m_currentProject))
1880                               && hasDeploySettings(d->m_currentProject);
1881
1882     const QString projectName = project ? project->displayName() : QString();
1883     const QString projectNameContextMenu = d->m_currentProject ? d->m_currentProject->displayName() : QString();
1884     bool hasProjects = !d->m_session->projects().isEmpty();
1885     bool building = d->m_buildManager->isBuilding();
1886
1887     d->m_deployAction->setParameter(projectName);
1888     d->m_deployAction->setEnabled(enableDeployActions);
1889
1890     d->m_deployActionContextMenu->setParameter(projectNameContextMenu);
1891     d->m_deployActionContextMenu->setEnabled(enableDeployActionsContextMenu);
1892
1893     d->m_deployProjectOnlyAction->setEnabled(enableDeployActions);
1894
1895     d->m_deploySessionAction->setEnabled(hasProjects && !building);
1896
1897     emit updateRunActions();
1898 }
1899
1900 bool ProjectExplorerPlugin::canRun(Project *project, const QString &runMode)
1901 {
1902     if (!project ||
1903         !project->activeTarget() ||
1904         !project->activeTarget()->activeRunConfiguration()) {
1905         return false;
1906     }
1907     RunConfiguration *activeRC = project->activeTarget()->activeRunConfiguration();
1908
1909     bool canRun = findRunControlFactory(activeRC, runMode)
1910                   && activeRC->isEnabled();
1911     const bool building = d->m_buildManager->isBuilding();
1912     return (canRun && !building);
1913 }
1914
1915 void ProjectExplorerPlugin::slotUpdateRunActions()
1916 {
1917     Project *project = startupProject();
1918     d->m_runAction->setEnabled(canRun(project, ProjectExplorer::Constants::RUNMODE));
1919 }
1920
1921 void ProjectExplorerPlugin::cancelBuild()
1922 {
1923     if (debug)
1924         qDebug() << "ProjectExplorerPlugin::cancelBuild";
1925
1926     if (d->m_buildManager->isBuilding())
1927         d->m_buildManager->cancel();
1928 }
1929
1930 void ProjectExplorerPlugin::addToRecentProjects(const QString &fileName, const QString &displayName)
1931 {
1932     if (debug)
1933         qDebug() << "ProjectExplorerPlugin::addToRecentProjects(" << fileName << ")";
1934
1935     if (fileName.isEmpty())
1936         return;
1937     QString prettyFileName(QDir::toNativeSeparators(fileName));
1938
1939     QList<QPair<QString, QString> >::iterator it;
1940     for(it = d->m_recentProjects.begin(); it != d->m_recentProjects.end();)
1941         if ((*it).first == prettyFileName)
1942             it = d->m_recentProjects.erase(it);
1943         else
1944             ++it;
1945
1946     if (d->m_recentProjects.count() > d->m_maxRecentProjects)
1947         d->m_recentProjects.removeLast();
1948     d->m_recentProjects.prepend(qMakePair(prettyFileName, displayName));
1949     QFileInfo fi(prettyFileName);
1950     d->m_lastOpenDirectory = fi.absolutePath();
1951 }
1952
1953 void ProjectExplorerPlugin::updateRecentProjectMenu()
1954 {
1955     typedef QList<QPair<QString, QString> >::const_iterator StringPairListConstIterator;
1956     if (debug)
1957         qDebug() << "ProjectExplorerPlugin::updateRecentProjectMenu";
1958
1959     Core::ActionContainer *aci =
1960         Core::ICore::instance()->actionManager()->actionContainer(Constants::M_RECENTPROJECTS);
1961     QMenu *menu = aci->menu();
1962     menu->clear();
1963
1964     menu->setEnabled(!d->m_recentProjects.isEmpty());
1965
1966     //projects (ignore sessions, they used to be in this list)
1967     const StringPairListConstIterator end = d->m_recentProjects.constEnd();
1968     for (StringPairListConstIterator it = d->m_recentProjects.constBegin(); it != end; ++it) {
1969         const QPair<QString, QString> &s = *it;
1970         if (s.first.endsWith(QLatin1String(".qws")))
1971             continue;
1972         QAction *action = menu->addAction(Utils::withTildeHomePath(s.first));
1973         action->setData(s.first);
1974         connect(action, SIGNAL(triggered()), this, SLOT(openRecentProject()));
1975     }
1976 }
1977
1978 void ProjectExplorerPlugin::openRecentProject()
1979 {
1980     if (debug)
1981         qDebug() << "ProjectExplorerPlugin::openRecentProject()";
1982
1983     QAction *a = qobject_cast<QAction*>(sender());
1984     if (!a)
1985         return;
1986     QString fileName = a->data().toString();
1987     if (!fileName.isEmpty())
1988         openProject(fileName);
1989 }
1990
1991 void ProjectExplorerPlugin::invalidateProject(Project *project)
1992 {
1993     if (debug)
1994         qDebug() << "ProjectExplorerPlugin::invalidateProject" << project->displayName();
1995     if (d->m_currentProject == project) {
1996         //
1997         // Workaround for a bug in QItemSelectionModel
1998         // - currentChanged etc are not emitted if the
1999         // item is removed from the underlying data model
2000         //
2001         setCurrent(0, QString(), 0);
2002     }
2003
2004     disconnect(project, SIGNAL(fileListChanged()), this, SIGNAL(fileListChanged()));
2005     updateActions();
2006 }
2007
2008 void ProjectExplorerPlugin::updateContextMenuActions()
2009 {
2010     d->m_addExistingFilesAction->setEnabled(false);
2011     d->m_addNewFileAction->setEnabled(false);
2012     d->m_addNewSubprojectAction->setEnabled(false);
2013     d->m_removeFileAction->setEnabled(false);
2014     d->m_deleteFileAction->setEnabled(false);
2015     d->m_renameFileAction->setEnabled(false);
2016
2017     d->m_addExistingFilesAction->setVisible(true);
2018     d->m_removeFileAction->setVisible(true);
2019     d->m_deleteFileAction->setVisible(true);
2020
2021     if (d->m_currentNode && d->m_currentNode->projectNode()) {
2022         QList<ProjectNode::ProjectAction> actions =
2023                 d->m_currentNode->projectNode()->supportedActions(d->m_currentNode);
2024
2025         if (qobject_cast<FolderNode*>(d->m_currentNode)) {
2026             d->m_addNewFileAction->setEnabled(actions.contains(ProjectNode::AddNewFile));
2027             d->m_addNewSubprojectAction->setEnabled(d->m_currentNode->nodeType() == ProjectNodeType
2028                                                     && actions.contains(ProjectNode::AddSubProject));
2029             d->m_addExistingFilesAction->setEnabled(actions.contains(ProjectNode::AddExistingFile));
2030             d->m_renameFileAction->setEnabled(actions.contains(ProjectNode::Rename));
2031         } else if (qobject_cast<FileNode*>(d->m_currentNode)) {
2032             // Enable and show remove / delete in magic ways:
2033             // If both are disabled show Remove
2034             // If both are enabled show both (can't happen atm)
2035             // If only removeFile is enabled only show it
2036             // If only deleteFile is enable only show it
2037             bool enableRemove = actions.contains(ProjectNode::RemoveFile);
2038             d->m_removeFileAction->setEnabled(enableRemove);
2039             bool enableDelete = actions.contains(ProjectNode::EraseFile);
2040             d->m_deleteFileAction->setEnabled(enableDelete);
2041             d->m_deleteFileAction->setVisible(enableDelete);
2042
2043             d->m_removeFileAction->setVisible(!enableDelete || enableRemove);
2044             d->m_renameFileAction->setEnabled(actions.contains(ProjectNode::Rename));
2045         }
2046     }
2047 }
2048
2049 QString ProjectExplorerPlugin::directoryFor(Node *node)
2050 {
2051     QString path = node->path();
2052     QString location;
2053     FolderNode *folder = qobject_cast<FolderNode *>(node);
2054     if (path.contains("#") && folder) {
2055         // Virtual Folder case
2056         // We figure out a commonPath from the subfolders
2057         QStringList list;
2058         foreach (FolderNode *f, folder->subFolderNodes())
2059             list << f->path() + "/";
2060         if (list.isEmpty())
2061             location = path.left(path.indexOf('#'));
2062         else
2063             location = Utils::commonPath(list);
2064     } else {
2065         QFileInfo fi(path);
2066         location = (fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath());
2067     }
2068     return location;
2069 }
2070
2071 void ProjectExplorerPlugin::addNewFile()
2072 {
2073     QTC_ASSERT(d->m_currentNode, return)
2074     QString location = directoryFor(d->m_currentNode);
2075
2076     Core::ICore::instance()->showNewItemDialog(tr("New File", "Title of dialog"),
2077                                Core::IWizard::wizardsOfKind(Core::IWizard::FileWizard)
2078                                + Core::IWizard::wizardsOfKind(Core::IWizard::ClassWizard),
2079                                location);
2080 }
2081
2082 void ProjectExplorerPlugin::addNewSubproject()
2083 {
2084     QTC_ASSERT(d->m_currentNode, return)
2085     QString location = directoryFor(d->m_currentNode);
2086
2087     if (d->m_currentNode->nodeType() == ProjectNodeType
2088             && d->m_currentNode->projectNode()->supportedActions(
2089                 d->m_currentNode->projectNode()).contains(ProjectNode::AddSubProject)) {
2090         Core::ICore::instance()->showNewItemDialog(tr("New Subproject", "Title of dialog"),
2091                               Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard),
2092                               location);
2093     }
2094 }
2095
2096 void ProjectExplorerPlugin::addExistingFiles()
2097 {
2098     QTC_ASSERT(d->m_currentNode, return)
2099
2100     ProjectNode *projectNode = qobject_cast<ProjectNode*>(d->m_currentNode->projectNode());
2101     Core::ICore *core = Core::ICore::instance();
2102     const QString dir = directoryFor(d->m_currentNode);
2103     QStringList fileNames = QFileDialog::getOpenFileNames(core->mainWindow(), tr("Add Existing Files"), dir);
2104     if (fileNames.isEmpty())
2105         return;
2106
2107     QHash<FileType, QString> fileTypeToFiles;
2108     foreach (const QString &fileName, fileNames) {
2109         FileType fileType = typeForFileName(core->mimeDatabase(), QFileInfo(fileName));
2110         fileTypeToFiles.insertMulti(fileType, fileName);
2111     }
2112
2113     QStringList notAdded;
2114     foreach (const FileType type, fileTypeToFiles.uniqueKeys()) {
2115         projectNode->addFiles(type, fileTypeToFiles.values(type), &notAdded);
2116     }
2117     if (!notAdded.isEmpty()) {
2118         QString message = tr("Could not add following files to project %1:\n").arg(projectNode->displayName());
2119         QString files = notAdded.join("\n");
2120         QMessageBox::warning(core->mainWindow(), tr("Adding Files to Project Failed"),
2121                              message + files);
2122         foreach (const QString &file, notAdded)
2123             fileNames.removeOne(file);
2124     }
2125
2126     if (Core::IVersionControl *vcManager = core->vcsManager()->findVersionControlForDirectory(dir))
2127         if (vcManager->supportsOperation(Core::IVersionControl::AddOperation)) {
2128             const QString files = fileNames.join(QString(QLatin1Char('\n')));
2129             QMessageBox::StandardButton button =
2130                 QMessageBox::question(core->mainWindow(), tr("Add to Version Control"),
2131                                       tr("Add files\n%1\nto version control (%2)?").arg(files, vcManager->displayName()),
2132                                       QMessageBox::Yes | QMessageBox::No);
2133             if (button == QMessageBox::Yes) {
2134                 QStringList notAddedToVc;
2135                 foreach (const QString &file, fileNames) {
2136                     if (!vcManager->vcsAdd(file))
2137                         notAddedToVc << file;
2138                 }
2139
2140                 if (!notAddedToVc.isEmpty()) {
2141                     const QString message = tr("Could not add following files to version control (%1)\n").arg(vcManager->displayName());
2142                     const QString filesNotAdded = notAddedToVc.join(QString(QLatin1Char('\n')));
2143                     QMessageBox::warning(core->mainWindow(), tr("Adding to Version Control Failed"),
2144                                          message + filesNotAdded);
2145                 }
2146             }
2147         }
2148 }
2149
2150 void ProjectExplorerPlugin::removeProject()
2151 {
2152     ProjectNode *subProjectNode = qobject_cast<ProjectNode*>(d->m_currentNode->projectNode());
2153     ProjectNode *projectNode = qobject_cast<ProjectNode *>(subProjectNode->parentFolderNode());
2154     if (projectNode) {
2155         Core::ICore *core = Core::ICore::instance();
2156         RemoveFileDialog removeFileDialog(subProjectNode->path(), core->mainWindow());
2157         removeFileDialog.setDeleteFileVisible(false);
2158         if (removeFileDialog.exec() == QDialog::Accepted)
2159             projectNode->removeSubProjects(QStringList() << subProjectNode->path());
2160     }
2161 }
2162
2163 void ProjectExplorerPlugin::openFile()
2164 {
2165     QTC_ASSERT(d->m_currentNode, return)
2166     Core::EditorManager *em = Core::EditorManager::instance();
2167     em->openEditor(d->m_currentNode->path(), QString(), Core::EditorManager::ModeSwitch);
2168 }
2169
2170 void ProjectExplorerPlugin::showInGraphicalShell()
2171 {
2172     QTC_ASSERT(d->m_currentNode, return)
2173     FolderNavigationWidget::showInGraphicalShell(Core::ICore::instance()->mainWindow(),
2174                                                  directoryFor(d->m_currentNode));
2175 }
2176
2177 void ProjectExplorerPlugin::openTerminalHere()
2178 {
2179     QTC_ASSERT(d->m_currentNode, return)
2180     FolderNavigationWidget::openTerminal(directoryFor(d->m_currentNode));
2181 }
2182
2183 void ProjectExplorerPlugin::removeFile()
2184 {
2185     QTC_ASSERT(d->m_currentNode && d->m_currentNode->nodeType() == FileNodeType, return)
2186
2187     FileNode *fileNode = qobject_cast<FileNode*>(d->m_currentNode);
2188     Core::ICore *core = Core::ICore::instance();
2189
2190     QString filePath = d->m_currentNode->path();
2191     RemoveFileDialog removeFileDialog(filePath, core->mainWindow());
2192
2193     if (removeFileDialog.exec() == QDialog::Accepted) {
2194         const bool deleteFile = removeFileDialog.isDeleteFileChecked();
2195
2196         // remove from project
2197         ProjectNode *projectNode = fileNode->projectNode();
2198         Q_ASSERT(projectNode);
2199
2200         if (!projectNode->removeFiles(fileNode->fileType(), QStringList(filePath))) {
2201             QMessageBox::warning(core->mainWindow(), tr("Removing File Failed"),
2202                                  tr("Could not remove file %1 from project %2.").arg(filePath).arg(projectNode->displayName()));
2203             return;
2204         }
2205
2206         // remove from version control
2207         core->vcsManager()->promptToDelete(filePath);
2208
2209         // remove from file system
2210         if (deleteFile) {
2211             QFile file(filePath);
2212
2213             if (file.exists()) {
2214                 // could have been deleted by vc
2215                 if (!file.remove())
2216                     QMessageBox::warning(core->mainWindow(), tr("Deleting File Failed"),
2217                                          tr("Could not delete file %1.").arg(filePath));
2218             }
2219         }
2220     }
2221 }
2222
2223 void ProjectExplorerPlugin::deleteFile()
2224 {
2225     QTC_ASSERT(d->m_currentNode && d->m_currentNode->nodeType() == FileNodeType, return)
2226
2227     FileNode *fileNode = qobject_cast<FileNode*>(d->m_currentNode);
2228     Core::ICore *core = Core::ICore::instance();
2229
2230     QString filePath = d->m_currentNode->path();
2231     QMessageBox::StandardButton button =
2232             QMessageBox::question(core->mainWindow(),
2233                                   tr("Delete File"),
2234                                   tr("Delete %1 from file system?").arg(filePath),
2235                                   QMessageBox::Yes | QMessageBox::No);
2236     if (button != QMessageBox::Yes)
2237         return;
2238
2239     ProjectNode *projectNode = fileNode->projectNode();
2240     Q_ASSERT(projectNode);
2241
2242     projectNode->deleteFiles(fileNode->fileType(), QStringList(filePath));
2243
2244     if (Core::IVersionControl *vc =
2245             core->vcsManager()->findVersionControlForDirectory(QFileInfo(filePath).absolutePath())) {
2246         vc->vcsDelete(filePath);
2247     }
2248     QFile file(filePath);
2249     if (file.exists()) {
2250         if (!file.remove())
2251             QMessageBox::warning(core->mainWindow(), tr("Deleting File Failed"),
2252                                  tr("Could not delete file %1.").arg(filePath));
2253     }
2254 }
2255
2256 void ProjectExplorerPlugin::renameFile()
2257 {
2258     QWidget *focusWidget = QApplication::focusWidget();
2259     while (focusWidget) {
2260         ProjectTreeWidget *treeWidget = qobject_cast<ProjectTreeWidget*>(focusWidget);
2261         if (treeWidget) {
2262             treeWidget->editCurrentItem();
2263             break;
2264         }
2265         focusWidget = focusWidget->parentWidget();
2266     }
2267 }
2268
2269 void ProjectExplorerPlugin::renameFile(Node *node, const QString &to)
2270 {
2271     FileNode *fileNode = qobject_cast<FileNode *>(node);
2272     if (!fileNode)
2273         return;
2274     QString orgFilePath = QFileInfo(node->path()).absoluteFilePath();
2275     QString dir = QFileInfo(orgFilePath).absolutePath();
2276     QString newFilePath = dir + "/" + to;
2277     Core::ICore *core = Core::ICore::instance();
2278     Core::IVersionControl *vc = core->vcsManager()->findVersionControlForDirectory(dir);
2279     bool result = false;
2280     if (vc && vc->supportsOperation(Core::IVersionControl::MoveOperation))
2281         result = vc->vcsMove(orgFilePath, newFilePath);
2282     if (!result) // The moving via vcs failed or the vcs does not support moving, fall back
2283         result = QFile::rename(orgFilePath, newFilePath);
2284     if (result) {
2285         // yeah we moved, tell the filemanager about it
2286         Core::ICore::instance()->fileManager()->renamedFile(orgFilePath, newFilePath);
2287         // Tell the project plugin about it
2288         ProjectNode *projectNode = fileNode->projectNode();
2289         projectNode->renameFile(fileNode->fileType(), orgFilePath, newFilePath);
2290         // TODO emit a signal?
2291     }
2292 }
2293
2294 void ProjectExplorerPlugin::setStartupProject()
2295 {
2296     setStartupProject(d->m_currentProject);
2297 }
2298
2299 void ProjectExplorerPlugin::populateOpenWithMenu(QMenu *menu, const QString &fileName)
2300 {
2301     typedef QList<Core::IEditorFactory*> EditorFactoryList;
2302     typedef QList<Core::IExternalEditor*> ExternalEditorList;
2303
2304     menu->clear();
2305
2306     bool anyMatches = false;
2307
2308     Core::ICore *core = Core::ICore::instance();
2309     if (const Core::MimeType mt = core->mimeDatabase()->findByFile(QFileInfo(fileName))) {
2310         const EditorFactoryList factories = core->editorManager()->editorFactories(mt, false);
2311         const ExternalEditorList externalEditors = core->editorManager()->externalEditors(mt, false);
2312         anyMatches = !factories.empty() || !externalEditors.empty();
2313         if (anyMatches) {
2314             // Add all suitable editors
2315             foreach (Core::IEditorFactory *editorFactory, factories) {
2316                 // Add action to open with this very editor factory
2317                 QString const actionTitle = editorFactory->displayName();
2318                 QAction * const action = menu->addAction(actionTitle);
2319                 action->setData(qVariantFromValue(editorFactory));
2320             }
2321             // Add all suitable external editors
2322             foreach (Core::IExternalEditor *externalEditor, externalEditors) {
2323                 QAction * const action = menu->addAction(externalEditor->displayName());
2324                 action->setData(qVariantFromValue(externalEditor));
2325             }
2326         }
2327     }
2328     menu->setEnabled(anyMatches);
2329 }
2330
2331 void ProjectExplorerPlugin::populateOpenWithMenu()
2332 {
2333     populateOpenWithMenu(d->m_openWithMenu, currentNode()->path());
2334 }
2335
2336 void ProjectExplorerPlugin::openWithMenuTriggered(QAction *action)
2337 {
2338     if (!action)
2339         qWarning() << "ProjectExplorerPlugin::openWithMenuTriggered no action, can't happen.";
2340     else
2341         openEditorFromAction(action, currentNode()->path());
2342 }
2343
2344 void ProjectExplorerPlugin::openEditorFromAction(QAction *action, const QString &fileName)
2345 {
2346     Core::EditorManager *em = Core::EditorManager::instance();
2347     const QVariant data = action->data();
2348     if (qVariantCanConvert<Core::IEditorFactory *>(data)) {
2349         Core::IEditorFactory *factory = qVariantValue<Core::IEditorFactory *>(data);
2350
2351         // close any open editors that have this file open, but have a different type.
2352         QList<Core::IEditor *> editorsOpenForFile = em->editorsForFileName(fileName);
2353         if (!editorsOpenForFile.isEmpty()) {
2354             foreach (Core::IEditor *openEditor, editorsOpenForFile) {
2355                 if (factory->id() == openEditor->id())
2356                     editorsOpenForFile.removeAll(openEditor);
2357             }
2358             if (!em->closeEditors(editorsOpenForFile)) // don't open if cancel was pressed
2359                 return;
2360         }
2361
2362         em->openEditor(fileName, factory->id(), Core::EditorManager::ModeSwitch);
2363         return;
2364     }
2365     if (qVariantCanConvert<Core::IExternalEditor *>(data)) {
2366         Core::IExternalEditor *externalEditor = qVariantValue<Core::IExternalEditor *>(data);
2367         em->openExternalEditor(fileName, externalEditor->id());
2368     }
2369 }
2370
2371 void ProjectExplorerPlugin::updateSessionMenu()
2372 {
2373     d->m_sessionMenu->clear();
2374     QActionGroup *ag = new QActionGroup(d->m_sessionMenu);
2375     connect(ag, SIGNAL(triggered(QAction *)), this, SLOT(setSession(QAction *)));
2376     const QString &activeSession = d->m_session->activeSession();
2377     foreach (const QString &session, d->m_session->sessions()) {
2378         QAction *act = ag->addAction(session);
2379         act->setCheckable(true);
2380         if (session == activeSession)
2381             act->setChecked(true);
2382     }
2383     d->m_sessionMenu->addActions(ag->actions());
2384     d->m_sessionMenu->addSeparator();
2385     d->m_sessionMenu->addAction(d->m_sessionManagerAction);
2386
2387     d->m_sessionMenu->setEnabled(true);
2388 }
2389
2390 void ProjectExplorerPlugin::setSession(QAction *action)
2391 {
2392     QString session = action->text();
2393     if (session != d->m_session->activeSession())
2394         d->m_session->loadSession(session);
2395 }
2396
2397
2398 void ProjectExplorerPlugin::setProjectExplorerSettings(const Internal::ProjectExplorerSettings &pes)
2399 {
2400     if (d->m_projectExplorerSettings == pes)
2401         return;
2402     d->m_projectExplorerSettings = pes;
2403     emit settingsChanged();
2404 }
2405
2406 Internal::ProjectExplorerSettings ProjectExplorerPlugin::projectExplorerSettings() const
2407 {
2408     return d->m_projectExplorerSettings;
2409 }
2410
2411 QStringList ProjectExplorerPlugin::projectFilePatterns()
2412 {
2413     QStringList patterns;
2414     const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase();
2415     foreach(const IProjectManager *pm, allProjectManagers())
2416         if (const Core::MimeType mt = mdb->findByType(pm->mimeType()))
2417             foreach(const Core::MimeGlobPattern &gp, mt.globPatterns())
2418                 patterns += gp.regExp().pattern();
2419     return patterns;
2420 }
2421
2422 void ProjectExplorerPlugin::openOpenProjectDialog()
2423 {
2424     Core::FileManager *fileMananger = Core::ICore::instance()->fileManager();
2425     const QString projectPatterns = ProjectExplorerPlugin::projectFilePatterns().join(QString(QLatin1Char(' ')));
2426     QString projectFilesFilter = tr("Projects (%1)").arg(projectPatterns);
2427     const QString allFilesFilter = tr("All Files (*)");
2428     const QString filters = allFilesFilter + QLatin1String(";;") + projectFilesFilter;
2429     const QString path = fileMananger->useProjectsDirectory() ? fileMananger->projectsDirectory() : QString();
2430     const QStringList files = fileMananger->getOpenFileNames(filters, path, &projectFilesFilter);
2431     if (!files.isEmpty())
2432         Core::ICore::instance()->openFiles(files, Core::ICore::SwitchMode);
2433 }
2434
2435 Q_EXPORT_PLUGIN(ProjectExplorerPlugin)