OSDN Git Service

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