1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
31 **************************************************************************/
33 #include "projectexplorer.h"
35 #include "buildsteplist.h"
36 #include "deployconfiguration.h"
37 #include "gcctoolchainfactories.h"
39 #include "projectexplorersettings.h"
41 #include "targetsettingspanel.h"
42 #include "toolchainmanager.h"
43 #include "toolchainoptionspage.h"
44 #include "copytaskhandler.h"
45 #include "showineditortaskhandler.h"
46 #include "vcsannotatetaskhandler.h"
47 #include "localapplicationruncontrol.h"
48 #include "allprojectsfilter.h"
49 #include "allprojectsfind.h"
50 #include "buildmanager.h"
51 #include "buildsettingspropertiespage.h"
52 #include "currentprojectfind.h"
53 #include "currentprojectfilter.h"
54 #include "customexecutablerunconfiguration.h"
55 #include "editorsettingspropertiespage.h"
56 #include "codestylesettingspropertiespage.h"
57 #include "dependenciespanel.h"
58 #include "foldernavigationwidget.h"
59 #include "iprojectmanager.h"
60 #include "metatypedeclarations.h"
61 #include "nodesvisitor.h"
62 #include "appoutputpane.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"
74 #include "projectnodes.h"
75 #include "sessiondialog.h"
77 #include "projectexplorersettingspage.h"
78 #include "projectwelcomepage.h"
79 #include "corelistenercheckingforrunningbuild.h"
80 #include "buildconfiguration.h"
81 #include "miniprojecttargetselector.h"
83 #include "publishing/ipublishingwizardfactory.h"
84 #include "publishing/publishingwizardselectiondialog.h"
87 # include "windebuginterface.h"
88 # include "msvctoolchain.h"
91 #include <coreplugin/coreconstants.h>
92 #include <coreplugin/filemanager.h>
93 #include <coreplugin/icore.h>
94 #include <coreplugin/imode.h>
95 #include <coreplugin/mimedatabase.h>
96 #include <coreplugin/modemanager.h>
97 #include <coreplugin/actionmanager/actionmanager.h>
98 #include <coreplugin/actionmanager/actioncontainer.h>
99 #include <coreplugin/actionmanager/command.h>
100 #include <coreplugin/uniqueidmanager.h>
101 #include <coreplugin/editormanager/editormanager.h>
102 #include <coreplugin/editormanager/ieditor.h>
103 #include <coreplugin/editormanager/ieditorfactory.h>
104 #include <coreplugin/editormanager/iexternaleditor.h>
105 #include <coreplugin/findplaceholder.h>
106 #include <coreplugin/basefilewizard.h>
107 #include <coreplugin/vcsmanager.h>
108 #include <coreplugin/iversioncontrol.h>
109 #include <coreplugin/variablemanager.h>
110 #include <coreplugin/fileutils.h>
111 #include <extensionsystem/pluginmanager.h>
112 #include <find/searchresultwindow.h>
113 #include <utils/consoleprocess.h>
114 #include <utils/qtcassert.h>
115 #include <utils/parameteraction.h>
116 #include <utils/stringutils.h>
118 #include <QtCore/QtPlugin>
119 #include <QtCore/QDateTime>
120 #include <QtCore/QDebug>
121 #include <QtCore/QSettings>
122 #include <QtCore/QAbstractFileEngine>
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>
133 \namespace ProjectExplorer
134 ProjectExplorer plugin namespace
138 \namespace ProjectExplorer::Internal
139 Internal namespace of the ProjectExplorer plugin
144 \class ProjectExplorer::ProjectExplorerPlugin
146 \brief ProjectExplorerPlugin with static accessor and utility functions to obtain
147 current project, open projects, etc.
150 Q_DECLARE_METATYPE(Core::IEditorFactory*)
151 Q_DECLARE_METATYPE(Core::IExternalEditor*)
157 static const char kCurrentProjectPath[] = "CurrentProject:Path";
158 static const char kCurrentProjectFilePath[] = "CurrentProject:FilePath";
160 namespace ProjectExplorer {
162 struct ProjectExplorerPluginPrivate {
163 ProjectExplorerPluginPrivate();
165 QMenu *m_sessionContextMenu;
166 QMenu *m_sessionMenu;
167 QMenu *m_projectMenu;
168 QMenu *m_subProjectMenu;
171 QMenu *m_openWithMenu;
173 QMultiMap<int, QObject*> m_actionMap;
174 QAction *m_sessionManagerAction;
175 QAction *m_newAction;
176 QAction *m_loadAction;
177 Utils::ParameterAction *m_unloadAction;
178 QAction *m_clearSession;
179 QAction *m_buildProjectOnlyAction;
180 Utils::ParameterAction *m_buildAction;
181 Utils::ParameterAction *m_buildActionContextMenu;
182 QAction *m_buildSessionAction;
183 QAction *m_rebuildProjectOnlyAction;
184 Utils::ParameterAction *m_rebuildAction;
185 Utils::ParameterAction *m_rebuildActionContextMenu;
186 QAction *m_rebuildSessionAction;
187 QAction *m_cleanProjectOnlyAction;
188 QAction *m_deployProjectOnlyAction;
189 Utils::ParameterAction *m_deployAction;
190 Utils::ParameterAction *m_deployActionContextMenu;
191 QAction *m_deploySessionAction;
192 Utils::ParameterAction *m_publishAction;
193 Utils::ParameterAction *m_cleanAction;
194 Utils::ParameterAction *m_cleanActionContextMenu;
195 QAction *m_cleanSessionAction;
196 QAction *m_runAction;
197 QAction *m_runActionContextMenu;
198 QAction *m_cancelBuildAction;
199 QAction *m_addNewFileAction;
200 QAction *m_addExistingFilesAction;
201 QAction *m_addNewSubprojectAction;
202 QAction *m_removeFileAction;
203 QAction *m_removeProjectAction;
204 QAction *m_deleteFileAction;
205 QAction *m_renameFileAction;
206 QAction *m_openFileAction;
207 QAction *m_projectTreeCollapseAllAction;
208 QAction *m_showInGraphicalShell;
209 QAction *m_openTerminalHere;
210 QAction *m_setStartupProjectAction;
211 QAction *m_projectSelectorAction;
212 QAction *m_projectSelectorActionMenu;
213 QAction *m_runSubProject;
215 Internal::ProjectWindow *m_proWindow;
216 SessionManager *m_session;
217 QString m_sessionToRestoreAtStartup;
219 Project *m_currentProject;
222 BuildManager *m_buildManager;
224 QList<Internal::ProjectFileFactory*> m_fileFactories;
225 QStringList m_profileMimeTypes;
226 Internal::AppOutputPane *m_outputPane;
228 QList<QPair<QString, QString> > m_recentProjects; // pair of filename, displayname
229 static const int m_maxRecentProjects = 7;
231 QString m_lastOpenDirectory;
232 RunConfiguration *m_delayedRunConfiguration; // TODO this is not right
234 QString m_projectFilterString;
235 Internal::MiniProjectTargetSelector * m_targetSelector;
236 Internal::ProjectExplorerSettings m_projectExplorerSettings;
237 Internal::ProjectWelcomePage *m_welcomePage;
239 Core::IMode *m_projectsMode;
241 ToolChainManager *m_toolChainManager;
244 ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() :
247 m_delayedRunConfiguration(0),
249 m_toolChainManager(0)
253 class ProjectsMode : public Core::IMode
256 ProjectsMode(QWidget *proWindow)
258 setWidget(proWindow);
259 setContext(Core::Context(Constants::C_PROJECTEXPLORER));
260 setDisplayName(QCoreApplication::translate("ProjectExplorer::ProjectsMode", "Projects"));
261 setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Project.png")));
262 setPriority(Constants::P_MODE_SESSION);
263 setId(QLatin1String(Constants::MODE_SESSION));
265 setContextHelpId(QLatin1String("Managing Projects"));
269 } // namespace ProjectExplorer
271 using namespace ProjectExplorer;
272 using namespace ProjectExplorer::Internal;
275 ProjectExplorerPlugin *ProjectExplorerPlugin::m_instance = 0;
277 ProjectExplorerPlugin::ProjectExplorerPlugin()
278 : d(new ProjectExplorerPluginPrivate)
283 ProjectExplorerPlugin::~ProjectExplorerPlugin()
285 removeObject(d->m_welcomePage);
286 delete d->m_welcomePage;
287 delete d->m_toolChainManager;
292 ProjectExplorerPlugin *ProjectExplorerPlugin::instance()
297 bool ProjectExplorerPlugin::parseArguments(const QStringList &arguments, QString * /* error */)
299 CustomWizard::setVerbose(arguments.count(QLatin1String("-customwizard-verbose")));
303 bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *error)
305 if (!parseArguments(arguments, error))
309 // Add ToolChainFactories:
311 addAutoReleasedObject(new WinDebugInterface);
313 addAutoReleasedObject(new Internal::MingwToolChainFactory);
314 addAutoReleasedObject(new Internal::MsvcToolChainFactory);
316 addAutoReleasedObject(new Internal::GccToolChainFactory);
317 addAutoReleasedObject(new Internal::LinuxIccToolChainFactory);
319 addAutoReleasedObject(new Internal::ClangToolChainFactory);
321 d->m_toolChainManager = new ToolChainManager(this);
323 addAutoReleasedObject(new Internal::ToolChainOptionsPage);
325 addAutoReleasedObject(new TaskHub);
327 Core::ICore *core = Core::ICore::instance();
328 Core::ActionManager *am = core->actionManager();
329 connect(core, SIGNAL(newItemsDialogRequested()), this, SLOT(loadCustomWizards()));
331 d->m_welcomePage = new ProjectWelcomePage;
332 connect(d->m_welcomePage, SIGNAL(manageSessions()), this, SLOT(showSessionManager()));
333 addObject(d->m_welcomePage);
335 connect(core->fileManager(), SIGNAL(currentFileChanged(QString)),
336 this, SLOT(setCurrentFile(QString)));
338 d->m_session = new SessionManager(this);
340 connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project *)),
341 this, SIGNAL(fileListChanged()));
342 connect(d->m_session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project *)),
343 this, SLOT(invalidateProject(ProjectExplorer::Project *)));
344 connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project *)),
345 this, SIGNAL(fileListChanged()));
346 connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
347 this, SLOT(projectAdded(ProjectExplorer::Project*)));
348 connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)),
349 this, SLOT(projectRemoved(ProjectExplorer::Project*)));
350 connect(d->m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project *)),
351 this, SLOT(startupProjectChanged()));
352 connect(d->m_session, SIGNAL(dependencyChanged(ProjectExplorer::Project*,ProjectExplorer::Project*)),
353 this, SLOT(updateActions()));
354 connect(d->m_session, SIGNAL(sessionLoaded()),
355 this, SLOT(updateActions()));
356 connect(d->m_session, SIGNAL(sessionLoaded()),
357 this, SLOT(updateWelcomePage()));
359 d->m_proWindow = new ProjectWindow;
361 Core::Context globalcontext(Core::Constants::C_GLOBAL);
362 Core::Context projecTreeContext(Constants::C_PROJECT_TREE);
364 d->m_projectsMode = new ProjectsMode(d->m_proWindow);
365 d->m_projectsMode->setEnabled(session()->startupProject());
366 addAutoReleasedObject(d->m_projectsMode);
367 d->m_proWindow->layout()->addWidget(new Core::FindToolBarPlaceHolder(d->m_proWindow));
369 addAutoReleasedObject(new CopyTaskHandler);
370 addAutoReleasedObject(new ShowInEditorTaskHandler);
371 addAutoReleasedObject(new VcsAnnotateTaskHandler);
373 d->m_buildManager = new BuildManager(this);
374 connect(d->m_buildManager, SIGNAL(buildStateChanged(ProjectExplorer::Project *)),
375 this, SLOT(buildStateChanged(ProjectExplorer::Project *)));
376 connect(d->m_buildManager, SIGNAL(buildQueueFinished(bool)),
377 this, SLOT(buildQueueFinished(bool)));
379 addAutoReleasedObject(new CoreListener);
381 d->m_outputPane = new AppOutputPane;
382 addAutoReleasedObject(d->m_outputPane);
383 connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project *)),
384 d->m_outputPane, SLOT(projectRemoved()));
386 AllProjectsFilter *allProjectsFilter = new AllProjectsFilter(this);
387 addAutoReleasedObject(allProjectsFilter);
389 CurrentProjectFilter *currentProjectFilter = new CurrentProjectFilter(this);
390 addAutoReleasedObject(currentProjectFilter);
392 addAutoReleasedObject(new BuildSettingsPanelFactory);
393 addAutoReleasedObject(new RunSettingsPanelFactory);
394 addAutoReleasedObject(new EditorSettingsPanelFactory);
395 addAutoReleasedObject(new CodeStyleSettingsPanelFactory);
396 addAutoReleasedObject(new DependenciesPanelFactory(d->m_session));
398 ProcessStepFactory *processStepFactory = new ProcessStepFactory;
399 addAutoReleasedObject(processStepFactory);
401 AllProjectsFind *allProjectsFind = new AllProjectsFind(this,
402 Find::SearchResultWindow::instance());
403 addAutoReleasedObject(allProjectsFind);
405 CurrentProjectFind *currentProjectFind = new CurrentProjectFind(this,
406 Find::SearchResultWindow::instance());
407 addAutoReleasedObject(currentProjectFind);
409 addAutoReleasedObject(new LocalApplicationRunControlFactory);
410 addAutoReleasedObject(new CustomExecutableRunConfigurationFactory);
412 addAutoReleasedObject(new ProjectFileWizardExtension);
415 addAutoReleasedObject(new ProjectExplorerSettingsPage);
418 Core::ActionContainer *msessionContextMenu =
419 am->createMenu(Constants::M_SESSIONCONTEXT);
420 Core::ActionContainer *mprojectContextMenu =
421 am->createMenu(Constants::M_PROJECTCONTEXT);
422 Core::ActionContainer *msubProjectContextMenu =
423 am->createMenu(Constants::M_SUBPROJECTCONTEXT);
424 Core::ActionContainer *mfolderContextMenu =
425 am->createMenu(Constants::M_FOLDERCONTEXT);
426 Core::ActionContainer *mfileContextMenu =
427 am->createMenu(Constants::M_FILECONTEXT);
429 d->m_sessionContextMenu = msessionContextMenu->menu();
430 d->m_projectMenu = mprojectContextMenu->menu();
431 d->m_subProjectMenu = msubProjectContextMenu->menu();
432 d->m_folderMenu = mfolderContextMenu->menu();
433 d->m_fileMenu = mfileContextMenu->menu();
435 Core::ActionContainer *mfile =
436 am->actionContainer(Core::Constants::M_FILE);
437 Core::ActionContainer *menubar =
438 am->actionContainer(Core::Constants::MENU_BAR);
440 // mode manager (for fancy actions)
441 Core::ModeManager *modeManager = core->modeManager();
444 Core::ActionContainer *mbuild =
445 am->createMenu(Constants::M_BUILDPROJECT);
446 mbuild->menu()->setTitle(tr("&Build"));
447 menubar->addMenu(mbuild, Core::Constants::G_VIEW);
450 Core::ActionContainer *mdebug =
451 am->createMenu(Constants::M_DEBUG);
452 mdebug->menu()->setTitle(tr("&Debug"));
453 menubar->addMenu(mdebug, Core::Constants::G_VIEW);
455 Core::ActionContainer *mstartdebugging =
456 am->createMenu(Constants::M_DEBUG_STARTDEBUGGING);
457 mstartdebugging->menu()->setTitle(tr("&Start Debugging"));
458 mdebug->addMenu(mstartdebugging, Core::Constants::G_DEFAULT_ONE);
464 mbuild->appendGroup(Constants::G_BUILD_SESSION);
465 mbuild->appendGroup(Constants::G_BUILD_PROJECT);
466 mbuild->appendGroup(Constants::G_BUILD_OTHER);
467 mbuild->appendGroup(Constants::G_BUILD_CANCEL);
468 mbuild->appendGroup(Constants::G_BUILD_RUN);
470 msessionContextMenu->appendGroup(Constants::G_SESSION_BUILD);
471 msessionContextMenu->appendGroup(Constants::G_SESSION_FILES);
472 msessionContextMenu->appendGroup(Constants::G_SESSION_OTHER);
473 msessionContextMenu->appendGroup(Constants::G_SESSION_CONFIG);
474 msessionContextMenu->appendGroup(Constants::G_PROJECT_TREE);
476 mprojectContextMenu->appendGroup(Constants::G_PROJECT_FIRST);
477 mprojectContextMenu->appendGroup(Constants::G_PROJECT_BUILD);
478 mprojectContextMenu->appendGroup(Constants::G_PROJECT_RUN);
479 mprojectContextMenu->appendGroup(Constants::G_PROJECT_FILES);
480 mprojectContextMenu->appendGroup(Constants::G_PROJECT_LAST);
481 mprojectContextMenu->appendGroup(Constants::G_PROJECT_TREE);
483 msubProjectContextMenu->appendGroup(Constants::G_PROJECT_FIRST);
484 msubProjectContextMenu->appendGroup(Constants::G_PROJECT_BUILD);
485 msubProjectContextMenu->appendGroup(Constants::G_PROJECT_RUN);
486 msubProjectContextMenu->appendGroup(Constants::G_PROJECT_FILES);
487 msubProjectContextMenu->appendGroup(Constants::G_PROJECT_LAST);
488 msubProjectContextMenu->appendGroup(Constants::G_PROJECT_TREE);
490 Core::ActionContainer *runMenu = Core::ICore::instance()->actionManager()->createMenu(Constants::RUNMENUCONTEXTMENU);
491 runMenu->setOnAllDisabledBehavior(Core::ActionContainer::Hide);
492 QIcon runIcon(Constants::ICON_RUN);
493 runIcon.addFile(Constants::ICON_RUN_SMALL);
494 runMenu->menu()->setIcon(runIcon);
495 runMenu->menu()->setTitle("Run");
496 msubProjectContextMenu->addMenu(runMenu, ProjectExplorer::Constants::G_PROJECT_RUN);
498 mfolderContextMenu->appendGroup(Constants::G_FOLDER_FILES);
499 mfolderContextMenu->appendGroup(Constants::G_FOLDER_OTHER);
500 mfolderContextMenu->appendGroup(Constants::G_FOLDER_CONFIG);
501 mfolderContextMenu->appendGroup(Constants::G_PROJECT_TREE);
503 mfileContextMenu->appendGroup(Constants::G_FILE_OPEN);
504 mfileContextMenu->appendGroup(Constants::G_FILE_OTHER);
505 mfileContextMenu->appendGroup(Constants::G_FILE_CONFIG);
506 mfileContextMenu->appendGroup(Constants::G_PROJECT_TREE);
507 // "open with" submenu
508 Core::ActionContainer * const openWith =
509 am->createMenu(ProjectExplorer::Constants::M_OPENFILEWITHCONTEXT);
510 openWith->setOnAllDisabledBehavior(Core::ActionContainer::Show);
511 d->m_openWithMenu = openWith->menu();
512 d->m_openWithMenu->setTitle(tr("Open With"));
514 connect(d->m_openWithMenu, SIGNAL(triggered(QAction *)),
515 this, SLOT(openWithMenuTriggered(QAction *)));
524 sep = new QAction(this);
525 sep->setSeparator(true);
526 cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Build.Sep"), globalcontext);
527 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
529 sep = new QAction(this);
530 sep->setSeparator(true);
531 cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Files.Sep"), projecTreeContext);
532 msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
533 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
534 msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
536 sep = new QAction(this);
537 sep->setSeparator(true);
538 cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Config.Sep"), projecTreeContext);
539 msessionContextMenu->addAction(cmd, Constants::G_SESSION_CONFIG);
541 sep = new QAction(this);
542 sep->setSeparator(true);
543 cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Projects.Sep"), globalcontext);
544 mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
546 sep = new QAction(this);
547 sep->setSeparator(true);
548 cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Other.Sep"), globalcontext);
549 mbuild->addAction(cmd, Constants::G_BUILD_OTHER);
550 msessionContextMenu->addAction(cmd, Constants::G_SESSION_OTHER);
552 sep = new QAction(this);
553 sep->setSeparator(true);
554 cmd = am->registerAction(sep, Core::Id("ProjectExplorer.Run.Sep"), globalcontext);
555 mbuild->addAction(cmd, Constants::G_BUILD_RUN);
556 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
558 sep = new QAction(this);
559 sep->setSeparator(true);
560 cmd = am->registerAction(sep, Core::Id("ProjectExplorer.CancelBuild.Sep"), globalcontext);
561 mbuild->addAction(cmd, Constants::G_BUILD_CANCEL);
568 d->m_newAction = new QAction(tr("New Project..."), this);
569 cmd = am->registerAction(d->m_newAction, Constants::NEWPROJECT, globalcontext);
570 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+N")));
571 msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
574 d->m_loadAction = new QAction(tr("Load Project..."), this);
575 cmd = am->registerAction(d->m_loadAction, Constants::LOAD, globalcontext);
577 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+O")));
579 msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
581 // Default open action
582 d->m_openFileAction = new QAction(tr("Open File"), this);
583 cmd = am->registerAction(d->m_openFileAction, ProjectExplorer::Constants::OPENFILE,
585 mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
587 d->m_showInGraphicalShell = new QAction(Core::Internal::FileUtils::msgGraphicalShellAction(), this);
588 cmd = am->registerAction(d->m_showInGraphicalShell, ProjectExplorer::Constants::SHOWINGRAPHICALSHELL,
590 mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
591 mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
593 d->m_openTerminalHere = new QAction(Core::Internal::FileUtils::msgTerminalAction(), this);
594 cmd = am->registerAction(d->m_openTerminalHere, ProjectExplorer::Constants::OPENTERMIANLHERE,
596 mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
597 mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
600 mfileContextMenu->addMenu(openWith, ProjectExplorer::Constants::G_FILE_OPEN);
602 // recent projects menu
603 Core::ActionContainer *mrecent =
604 am->createMenu(Constants::M_RECENTPROJECTS);
605 mrecent->menu()->setTitle(tr("Recent P&rojects"));
606 mrecent->setOnAllDisabledBehavior(Core::ActionContainer::Show);
607 mfile->addMenu(mrecent, Core::Constants::G_FILE_OPEN);
608 connect(mfile->menu(), SIGNAL(aboutToShow()),
609 this, SLOT(updateRecentProjectMenu()));
611 // recent session menu
612 Core::ActionContainer *msession = am->createMenu(Constants::M_SESSION);
613 msession->menu()->setTitle(tr("Recent Sessions"));
614 msession->setOnAllDisabledBehavior(Core::ActionContainer::Show);
615 mfile->addMenu(msession, Core::Constants::G_FILE_OPEN);
616 d->m_sessionMenu = msession->menu();
617 connect(mfile->menu(), SIGNAL(aboutToShow()),
618 this, SLOT(updateSessionMenu()));
620 // session manager action
621 d->m_sessionManagerAction = new QAction(tr("Session Manager..."), this);
622 cmd = am->registerAction(d->m_sessionManagerAction, Constants::NEWSESSION, globalcontext);
623 mfile->addAction(cmd, Core::Constants::G_FILE_OPEN);
624 cmd->setDefaultKeySequence(QKeySequence());
629 d->m_unloadAction = new Utils::ParameterAction(tr("Close Project"), tr("Close Project \"%1\""),
630 Utils::ParameterAction::EnabledWithParameter, this);
631 cmd = am->registerAction(d->m_unloadAction, Constants::UNLOAD, globalcontext);
632 cmd->setAttribute(Core::Command::CA_UpdateText);
633 cmd->setDefaultText(d->m_unloadAction->text());
634 mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
636 // unload session action
637 d->m_clearSession = new QAction(tr("Close All Projects"), this);
638 cmd = am->registerAction(d->m_clearSession, Constants::CLEARSESSION, globalcontext);
639 mfile->addAction(cmd, Core::Constants::G_FILE_PROJECT);
640 msessionContextMenu->addAction(cmd, Constants::G_SESSION_FILES);
642 // build session action
643 QIcon buildIcon(Constants::ICON_BUILD);
644 buildIcon.addFile(Constants::ICON_BUILD_SMALL);
645 d->m_buildSessionAction = new QAction(buildIcon, tr("Build All"), this);
646 cmd = am->registerAction(d->m_buildSessionAction, Constants::BUILDSESSION, globalcontext);
647 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+B")));
648 mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
649 msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
651 // rebuild session action
652 QIcon rebuildIcon(Constants::ICON_REBUILD);
653 rebuildIcon.addFile(Constants::ICON_REBUILD_SMALL);
654 d->m_rebuildSessionAction = new QAction(rebuildIcon, tr("Rebuild All"), this);
655 cmd = am->registerAction(d->m_rebuildSessionAction, Constants::REBUILDSESSION, globalcontext);
656 mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
657 msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
660 d->m_deploySessionAction = new QAction(tr("Deploy All"), this);
661 cmd = am->registerAction(d->m_deploySessionAction, Constants::DEPLOYSESSION, globalcontext);
662 mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
663 msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
666 QIcon cleanIcon(Constants::ICON_CLEAN);
667 cleanIcon.addFile(Constants::ICON_CLEAN_SMALL);
668 d->m_cleanSessionAction = new QAction(cleanIcon, tr("Clean All"), this);
669 cmd = am->registerAction(d->m_cleanSessionAction, Constants::CLEANSESSION, globalcontext);
670 mbuild->addAction(cmd, Constants::G_BUILD_SESSION);
671 msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
674 d->m_buildAction = new Utils::ParameterAction(tr("Build Project"), tr("Build Project \"%1\""),
675 Utils::ParameterAction::AlwaysEnabled, this);
676 d->m_buildAction->setIcon(buildIcon);
677 cmd = am->registerAction(d->m_buildAction, Constants::BUILD, globalcontext);
678 cmd->setAttribute(Core::Command::CA_UpdateText);
679 cmd->setDefaultText(d->m_buildAction->text());
680 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+B")));
681 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
684 modeManager->addAction(cmd->action(), Constants::P_ACTION_BUILDPROJECT);
687 d->m_rebuildAction = new Utils::ParameterAction(tr("Rebuild Project"), tr("Rebuild Project \"%1\""),
688 Utils::ParameterAction::AlwaysEnabled, this);
689 cmd = am->registerAction(d->m_rebuildAction, Constants::REBUILD, globalcontext);
690 cmd->setAttribute(Core::Command::CA_UpdateText);
691 cmd->setDefaultText(d->m_rebuildAction->text());
692 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
695 d->m_deployAction = new Utils::ParameterAction(tr("Deploy Project"), tr("Deploy Project \"%1\""),
696 Utils::ParameterAction::AlwaysEnabled, this);
697 cmd = am->registerAction(d->m_deployAction, Constants::DEPLOY, globalcontext);
698 cmd->setAttribute(Core::Command::CA_UpdateText);
699 cmd->setDefaultText(d->m_deployAction->text());
700 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
703 d->m_publishAction = new Utils::ParameterAction(tr("Publish Project..."), tr("Publish Project \"%1\"..."),
704 Utils::ParameterAction::AlwaysEnabled, this);
705 cmd = am->registerAction(d->m_publishAction, Constants::PUBLISH, globalcontext);
706 cmd->setAttribute(Core::Command::CA_UpdateText);
707 cmd->setDefaultText(d->m_publishAction->text());
708 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
711 d->m_cleanAction = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""),
712 Utils::ParameterAction::AlwaysEnabled, this);
713 cmd = am->registerAction(d->m_cleanAction, Constants::CLEAN, globalcontext);
714 cmd->setAttribute(Core::Command::CA_UpdateText);
715 cmd->setDefaultText(d->m_cleanAction->text());
716 mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
718 // build action (context menu)
719 d->m_buildActionContextMenu = new Utils::ParameterAction(tr("Build Project"), tr("Build Project \"%1\""),
720 Utils::ParameterAction::AlwaysEnabled, this);
721 cmd = am->registerAction(d->m_buildActionContextMenu, Constants::BUILDCM, projecTreeContext);
722 cmd->setAttribute(Core::Command::CA_UpdateText);
723 cmd->setDefaultText(d->m_buildActionContextMenu->text());
724 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
726 // rebuild action (context menu)
727 d->m_rebuildActionContextMenu = new Utils::ParameterAction(tr("Rebuild Project"), tr("Rebuild Project \"%1\""),
728 Utils::ParameterAction::AlwaysEnabled, this);
729 cmd = am->registerAction(d->m_rebuildActionContextMenu, Constants::REBUILDCM, projecTreeContext);
730 cmd->setAttribute(Core::Command::CA_UpdateText);
731 cmd->setDefaultText(d->m_rebuildActionContextMenu->text());
732 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
734 // deploy action (context menu)
735 d->m_deployActionContextMenu = new Utils::ParameterAction(tr("Deploy Project"), tr("Deploy Project \"%1\""),
736 Utils::ParameterAction::AlwaysEnabled, this);
737 cmd = am->registerAction(d->m_deployActionContextMenu, Constants::DEPLOYCM, projecTreeContext);
738 cmd->setAttribute(Core::Command::CA_UpdateText);
739 cmd->setDefaultText(d->m_deployActionContextMenu->text());
740 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
742 // clean action (context menu)
743 d->m_cleanActionContextMenu = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""),
744 Utils::ParameterAction::AlwaysEnabled, this);
745 cmd = am->registerAction(d->m_cleanActionContextMenu, Constants::CLEANCM, projecTreeContext);
746 cmd->setAttribute(Core::Command::CA_UpdateText);
747 cmd->setDefaultText(d->m_cleanActionContextMenu->text());
748 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_BUILD);
750 // build without dependencies action
751 d->m_buildProjectOnlyAction = new QAction(tr("Build Without Dependencies"), this);
752 cmd = am->registerAction(d->m_buildProjectOnlyAction, Constants::BUILDPROJECTONLY, globalcontext);
754 // rebuild without dependencies action
755 d->m_rebuildProjectOnlyAction = new QAction(tr("Rebuild Without Dependencies"), this);
756 cmd = am->registerAction(d->m_rebuildProjectOnlyAction, Constants::REBUILDPROJECTONLY, globalcontext);
758 // deploy without dependencies action
759 d->m_deployProjectOnlyAction = new QAction(tr("Deploy Without Dependencies"), this);
760 cmd = am->registerAction(d->m_deployProjectOnlyAction, Constants::DEPLOYPROJECTONLY, globalcontext);
762 // clean without dependencies action
763 d->m_cleanProjectOnlyAction = new QAction(tr("Clean Without Dependencies"), this);
764 cmd = am->registerAction(d->m_cleanProjectOnlyAction, Constants::CLEANPROJECTONLY, globalcontext);
767 d->m_runAction = new QAction(runIcon, tr("Run"), this);
768 cmd = am->registerAction(d->m_runAction, Constants::RUN, globalcontext);
769 cmd->setAttribute(Core::Command::CA_UpdateText);
771 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+R")));
772 mbuild->addAction(cmd, Constants::G_BUILD_RUN);
774 modeManager->addAction(cmd->action(), Constants::P_ACTION_RUN);
776 d->m_runActionContextMenu = new QAction(runIcon, tr("Run"), this);
777 cmd = am->registerAction(d->m_runActionContextMenu, Constants::RUNCONTEXTMENU, projecTreeContext);
778 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
779 msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
781 // cancel build action
782 d->m_cancelBuildAction = new QAction(tr("Cancel Build"), this);
783 cmd = am->registerAction(d->m_cancelBuildAction, Constants::CANCELBUILD, globalcontext);
784 mbuild->addAction(cmd, Constants::G_BUILD_CANCEL);
786 // add new file action
787 d->m_addNewFileAction = new QAction(tr("Add New..."), this);
788 cmd = am->registerAction(d->m_addNewFileAction, ProjectExplorer::Constants::ADDNEWFILE,
790 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
791 msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
792 mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
794 // add existing file action
795 d->m_addExistingFilesAction = new QAction(tr("Add Existing Files..."), this);
796 cmd = am->registerAction(d->m_addExistingFilesAction, ProjectExplorer::Constants::ADDEXISTINGFILES,
798 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
799 msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
800 mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
802 // new subproject action
803 d->m_addNewSubprojectAction = new QAction(tr("New Subproject..."), this);
804 cmd = am->registerAction(d->m_addNewSubprojectAction, ProjectExplorer::Constants::ADDNEWSUBPROJECT,
806 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
807 msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
809 // unload project again, in right position
810 mprojectContextMenu->addAction(am->command(Constants::UNLOAD), Constants::G_PROJECT_LAST);
812 // remove file action
813 d->m_removeFileAction = new QAction(tr("Remove File..."), this);
814 cmd = am->registerAction(d->m_removeFileAction, ProjectExplorer::Constants::REMOVEFILE,
816 cmd->setDefaultKeySequence(QKeySequence::Delete);
817 mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
819 //: Remove project from parent profile (Project explorer view); will not physically delete any files.
820 d->m_removeProjectAction = new QAction(tr("Remove Project..."), this);
821 cmd = am->registerAction(d->m_removeProjectAction, ProjectExplorer::Constants::REMOVEPROJECT,
823 msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
825 // delete file action
826 d->m_deleteFileAction = new QAction(tr("Delete File..."), this);
827 cmd = am->registerAction(d->m_deleteFileAction, ProjectExplorer::Constants::DELETEFILE,
829 cmd->setDefaultKeySequence(QKeySequence::Delete);
830 mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
833 d->m_renameFileAction = new QAction(tr("Rename"), this);
834 cmd = am->registerAction(d->m_renameFileAction, ProjectExplorer::Constants::RENAMEFILE,
836 mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
837 // Not yet used by anyone, so hide for now
838 // mfolder->addAction(cmd, Constants::G_FOLDER_FILES);
839 // msubProject->addAction(cmd, Constants::G_FOLDER_FILES);
840 // mproject->addAction(cmd, Constants::G_FOLDER_FILES);
842 // set startup project action
843 d->m_setStartupProjectAction = new QAction(tr("Set as Active Project"), this);
844 cmd = am->registerAction(d->m_setStartupProjectAction, ProjectExplorer::Constants::SETSTARTUP,
846 mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FIRST);
849 sep = new QAction(this);
850 sep->setSeparator(true);
851 Core::Command *treeSpacer = am->registerAction(sep, Core::Id("ProjectExplorer.Tree.Sep"), globalcontext);
853 d->m_projectTreeCollapseAllAction = new QAction(tr("Collapse All"), this);
854 cmd = am->registerAction(d->m_projectTreeCollapseAllAction, Constants::PROJECTTREE_COLLAPSE_ALL,
856 const QString treeGroup = QLatin1String(Constants::G_PROJECT_TREE);
857 mfileContextMenu->addAction(treeSpacer, treeGroup);
858 mfileContextMenu->addAction(cmd, treeGroup);
859 msubProjectContextMenu->addAction(treeSpacer, treeGroup);
860 msubProjectContextMenu->addAction(cmd, treeGroup);
861 mfolderContextMenu->addAction(treeSpacer, treeGroup);
862 mfolderContextMenu->addAction(cmd, treeGroup);
863 mprojectContextMenu->addAction(treeSpacer, treeGroup);
864 mprojectContextMenu->addAction(cmd, treeGroup);
865 msessionContextMenu->addAction(treeSpacer, treeGroup);
866 msessionContextMenu->addAction(cmd, treeGroup);
869 d->m_projectSelectorAction = new QAction(this);
870 d->m_projectSelectorAction->setCheckable(true);
871 d->m_projectSelectorAction->setEnabled(false);
872 QWidget *mainWindow = Core::ICore::instance()->mainWindow();
873 d->m_targetSelector = new Internal::MiniProjectTargetSelector(d->m_projectSelectorAction, mainWindow);
874 connect(d->m_projectSelectorAction, SIGNAL(triggered()), d->m_targetSelector, SLOT(show()));
875 modeManager->addProjectSelector(d->m_projectSelectorAction);
877 d->m_projectSelectorActionMenu = new QAction(this);
878 d->m_projectSelectorActionMenu->setEnabled(false);
879 d->m_projectSelectorActionMenu->setText(tr("Open Build/Run Target Selector..."));
880 connect(d->m_projectSelectorActionMenu, SIGNAL(triggered()), d->m_targetSelector, SLOT(show()));
881 cmd = am->registerAction(d->m_projectSelectorActionMenu, ProjectExplorer::Constants::SELECTTARGET,
883 cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+T")));
884 mbuild->addAction(cmd, Constants::G_BUILD_RUN);
886 connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
887 d->m_targetSelector, SLOT(addProject(ProjectExplorer::Project*)));
888 connect(d->m_session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
889 d->m_targetSelector, SLOT(removeProject(ProjectExplorer::Project*)));
890 connect(d->m_targetSelector, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
891 this, SLOT(setStartupProject(ProjectExplorer::Project*)));
892 connect(d->m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
893 d->m_targetSelector, SLOT(changeStartupProject(ProjectExplorer::Project*)));
895 connect(core, SIGNAL(saveSettingsRequested()),
896 this, SLOT(savePersistentSettings()));
898 addAutoReleasedObject(new ProjectTreeWidgetFactory);
899 addAutoReleasedObject(new FolderNavigationWidgetFactory);
900 addAutoReleasedObject(new DeployConfigurationFactory);
902 if (QSettings *s = core->settings()) {
903 const QStringList fileNames = s->value("ProjectExplorer/RecentProjects/FileNames").toStringList();
904 const QStringList displayNames = s->value("ProjectExplorer/RecentProjects/DisplayNames").toStringList();
905 if (fileNames.size() == displayNames.size()) {
906 for (int i = 0; i < fileNames.size(); ++i) {
907 if (QFileInfo(fileNames.at(i)).isFile())
908 d->m_recentProjects.append(qMakePair(fileNames.at(i), displayNames.at(i)));
913 if (QSettings *s = core->settings()) {
914 d->m_projectExplorerSettings.buildBeforeDeploy = s->value("ProjectExplorer/Settings/BuildBeforeDeploy", true).toBool();
915 d->m_projectExplorerSettings.deployBeforeRun = s->value("ProjectExplorer/Settings/DeployBeforeRun", true).toBool();
916 d->m_projectExplorerSettings.saveBeforeBuild = s->value("ProjectExplorer/Settings/SaveBeforeBuild", false).toBool();
917 d->m_projectExplorerSettings.showCompilerOutput = s->value("ProjectExplorer/Settings/ShowCompilerOutput", false).toBool();
918 d->m_projectExplorerSettings.showRunOutput = s->value("ProjectExplorer/Settings/ShowRunOutput", true).toBool();
919 d->m_projectExplorerSettings.cleanOldAppOutput = s->value("ProjectExplorer/Settings/CleanOldAppOutput", false).toBool();
920 d->m_projectExplorerSettings.mergeStdErrAndStdOut = s->value("ProjectExplorer/Settings/MergeStdErrAndStdOut", false).toBool();
921 d->m_projectExplorerSettings.wrapAppOutput = s->value("ProjectExplorer/Settings/WrapAppOutput", true).toBool();
922 d->m_projectExplorerSettings.useJom = s->value("ProjectExplorer/Settings/UseJom", true).toBool();
923 d->m_projectExplorerSettings.autorestoreLastSession = s->value("ProjectExplorer/Settings/AutoRestoreLastSession", false).toBool();
924 d->m_projectExplorerSettings.prompToStopRunControl = s->value("ProjectExplorer/Settings/PromptToStopRunControl", false).toBool();
925 d->m_projectExplorerSettings.maxAppOutputLines = s->value("ProjectExplorer/Settings/MaxAppOutputLines", 100000).toInt();
926 d->m_projectExplorerSettings.environmentId = QUuid(s->value("ProjectExplorer/Settings/EnvironmentId").toString());
927 if (d->m_projectExplorerSettings.environmentId.isNull())
928 d->m_projectExplorerSettings.environmentId = QUuid::createUuid();
931 connect(d->m_sessionManagerAction, SIGNAL(triggered()), this, SLOT(showSessionManager()));
932 connect(d->m_newAction, SIGNAL(triggered()), this, SLOT(newProject()));
933 connect(d->m_loadAction, SIGNAL(triggered()), this, SLOT(loadAction()));
934 connect(d->m_buildProjectOnlyAction, SIGNAL(triggered()), this, SLOT(buildProjectOnly()));
935 connect(d->m_buildAction, SIGNAL(triggered()), this, SLOT(buildProject()));
936 connect(d->m_buildActionContextMenu, SIGNAL(triggered()), this, SLOT(buildProjectContextMenu()));
937 connect(d->m_buildSessionAction, SIGNAL(triggered()), this, SLOT(buildSession()));
938 connect(d->m_rebuildProjectOnlyAction, SIGNAL(triggered()), this, SLOT(rebuildProjectOnly()));
939 connect(d->m_rebuildAction, SIGNAL(triggered()), this, SLOT(rebuildProject()));
940 connect(d->m_rebuildActionContextMenu, SIGNAL(triggered()), this, SLOT(rebuildProjectContextMenu()));
941 connect(d->m_rebuildSessionAction, SIGNAL(triggered()), this, SLOT(rebuildSession()));
942 connect(d->m_deployProjectOnlyAction, SIGNAL(triggered()), this, SLOT(deployProjectOnly()));
943 connect(d->m_deployAction, SIGNAL(triggered()), this, SLOT(deployProject()));
944 connect(d->m_deployActionContextMenu, SIGNAL(triggered()), this, SLOT(deployProjectContextMenu()));
945 connect(d->m_deploySessionAction, SIGNAL(triggered()), this, SLOT(deploySession()));
946 connect(d->m_publishAction, SIGNAL(triggered()), this, SLOT(publishProject()));
947 connect(d->m_cleanProjectOnlyAction, SIGNAL(triggered()), this, SLOT(cleanProjectOnly()));
948 connect(d->m_cleanAction, SIGNAL(triggered()), this, SLOT(cleanProject()));
949 connect(d->m_cleanActionContextMenu, SIGNAL(triggered()), this, SLOT(cleanProjectContextMenu()));
950 connect(d->m_cleanSessionAction, SIGNAL(triggered()), this, SLOT(cleanSession()));
951 connect(d->m_runAction, SIGNAL(triggered()), this, SLOT(runProject()));
952 connect(d->m_runActionContextMenu, SIGNAL(triggered()), this, SLOT(runProjectContextMenu()));
953 connect(d->m_cancelBuildAction, SIGNAL(triggered()), this, SLOT(cancelBuild()));
954 connect(d->m_unloadAction, SIGNAL(triggered()), this, SLOT(unloadProject()));
955 connect(d->m_clearSession, SIGNAL(triggered()), this, SLOT(clearSession()));
956 connect(d->m_addNewFileAction, SIGNAL(triggered()), this, SLOT(addNewFile()));
957 connect(d->m_addExistingFilesAction, SIGNAL(triggered()), this, SLOT(addExistingFiles()));
958 connect(d->m_addNewSubprojectAction, SIGNAL(triggered()), this, SLOT(addNewSubproject()));
959 connect(d->m_removeProjectAction, SIGNAL(triggered()), this, SLOT(removeProject()));
960 connect(d->m_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
961 connect(d->m_showInGraphicalShell, SIGNAL(triggered()), this, SLOT(showInGraphicalShell()));
962 connect(d->m_openTerminalHere, SIGNAL(triggered()), this, SLOT(openTerminalHere()));
963 connect(d->m_removeFileAction, SIGNAL(triggered()), this, SLOT(removeFile()));
964 connect(d->m_deleteFileAction, SIGNAL(triggered()), this, SLOT(deleteFile()));
965 connect(d->m_renameFileAction, SIGNAL(triggered()), this, SLOT(renameFile()));
966 connect(d->m_setStartupProjectAction, SIGNAL(triggered()), this, SLOT(setStartupProject()));
968 connect(this, SIGNAL(updateRunActions()), this, SLOT(slotUpdateRunActions()));
972 connect(Core::ICore::instance(), SIGNAL(coreAboutToOpen()),
973 this, SLOT(determineSessionToRestoreAtStartup()));
974 connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(restoreSession()));
978 Core::VariableManager *vm = Core::VariableManager::instance();
979 vm->registerVariable(QLatin1String(kCurrentProjectFilePath),
980 tr("Full path of the current project's main file, including file name."));
981 vm->registerVariable(QLatin1String(kCurrentProjectPath),
982 tr("Full path of the current project's main file, excluding file name."));
983 connect(vm, SIGNAL(variableUpdateRequested(QString)),
984 this, SLOT(updateVariable(QString)));
989 void ProjectExplorerPlugin::loadAction()
992 qDebug() << "ProjectExplorerPlugin::loadAction";
995 QString dir = d->m_lastOpenDirectory;
997 // for your special convenience, we preselect a pro file if it is
999 if (Core::IEditor *editor = Core::EditorManager::instance()->currentEditor()) {
1000 if (const Core::IFile *file = editor->file()) {
1001 const QString fn = file->fileName();
1002 const bool isProject = d->m_profileMimeTypes.contains(file->mimeType());
1003 dir = isProject ? fn : QFileInfo(fn).absolutePath();
1007 QString filename = QFileDialog::getOpenFileName(0, tr("Load Project"),
1009 d->m_projectFilterString);
1010 if (filename.isEmpty())
1012 openProject(filename);
1016 void ProjectExplorerPlugin::unloadProject()
1019 qDebug() << "ProjectExplorerPlugin::unloadProject";
1021 Core::IFile *fi = d->m_currentProject->file();
1023 if (!fi || fi->fileName().isEmpty()) //nothing to save?
1026 QList<Core::IFile*> filesToSave;
1029 // check the number of modified files
1030 int readonlycount = 0;
1031 foreach (const Core::IFile *file, filesToSave) {
1032 if (file->isReadOnly())
1036 bool success = false;
1037 if (readonlycount > 0)
1038 success = Core::ICore::instance()->fileManager()->saveModifiedFiles(filesToSave).isEmpty();
1040 success = Core::ICore::instance()->fileManager()->saveModifiedFilesSilently(filesToSave).isEmpty();
1045 addToRecentProjects(fi->fileName(), d->m_currentProject->displayName());
1046 d->m_session->removeProject(d->m_currentProject);
1050 void ProjectExplorerPlugin::clearSession()
1053 qDebug() << "ProjectExplorerPlugin::clearSession";
1055 if (!d->m_session->clear())
1056 return; // Action has been cancelled
1060 void ProjectExplorerPlugin::extensionsInitialized()
1062 d->m_toolChainManager->restoreToolChains();
1064 d->m_proWindow->extensionsInitialized();
1065 d->m_fileFactories = ProjectFileFactory::createFactories(&d->m_projectFilterString);
1066 foreach (ProjectFileFactory *pf, d->m_fileFactories) {
1067 d->m_profileMimeTypes += pf->mimeTypes();
1068 addAutoReleasedObject(pf);
1070 d->m_buildManager->extensionsInitialized();
1073 void ProjectExplorerPlugin::loadCustomWizards()
1075 // Add custom wizards, for which other plugins might have registered
1077 static bool firstTime = true;
1080 foreach(Core::IWizard *cpw, ProjectExplorer::CustomWizard::createWizards())
1081 addAutoReleasedObject(cpw);
1085 void ProjectExplorerPlugin::updateVariable(const QString &variable)
1087 if (variable == QLatin1String(kCurrentProjectFilePath)) {
1088 if (currentProject() && currentProject()->file()) {
1089 Core::VariableManager::instance()->insert(variable,
1090 currentProject()->file()->fileName());
1092 Core::VariableManager::instance()->remove(variable);
1094 } else if (variable == QLatin1String(kCurrentProjectPath)) {
1095 if (currentProject() && currentProject()->file()) {
1096 Core::VariableManager::instance()->insert(variable,
1097 QFileInfo(currentProject()->file()->fileName()).path());
1099 Core::VariableManager::instance()->remove(variable);
1104 ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown()
1106 d->m_proWindow->aboutToShutdown(); // disconnect from session
1107 d->m_session->clear();
1108 d->m_projectsMode = 0;
1109 // Attempt to synchronously shutdown all run controls.
1110 // If that fails, fall back to asynchronous shutdown (Debugger run controls
1111 // might shutdown asynchronously).
1112 if (d->m_outputPane->closeTabs(AppOutputPane::CloseTabNoPrompt /* No prompt any more */))
1113 return SynchronousShutdown;
1114 connect(d->m_outputPane, SIGNAL(allRunControlsFinished()),
1115 this, SIGNAL(asynchronousShutdownFinished()));
1116 return AsynchronousShutdown;
1119 void ProjectExplorerPlugin::newProject()
1122 qDebug() << "ProjectExplorerPlugin::newProject";
1124 Core::ICore::instance()->showNewItemDialog(tr("New Project", "Title of dialog"),
1125 Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard));
1129 void ProjectExplorerPlugin::showSessionManager()
1132 qDebug() << "ProjectExplorerPlugin::showSessionManager";
1134 if (d->m_session->isDefaultVirgin()) {
1135 // do not save new virgin default sessions
1137 d->m_session->save();
1139 SessionDialog sessionDialog(d->m_session);
1140 sessionDialog.setAutoLoadSession(d->m_projectExplorerSettings.autorestoreLastSession);
1141 sessionDialog.exec();
1142 d->m_projectExplorerSettings.autorestoreLastSession = sessionDialog.autoLoadSession();
1146 Core::ModeManager *modeManager = Core::ModeManager::instance();
1147 Core::IMode *welcomeMode = modeManager->mode(Core::Constants::MODE_WELCOME);
1148 if (modeManager->currentMode() == welcomeMode)
1149 updateWelcomePage();
1152 void ProjectExplorerPlugin::setStartupProject(Project *project)
1155 qDebug() << "ProjectExplorerPlugin::setStartupProject";
1159 d->m_session->setStartupProject(project);
1163 void ProjectExplorerPlugin::publishProject()
1165 const Project * const project = d->m_session->startupProject();
1166 QTC_ASSERT(project, return);
1167 PublishingWizardSelectionDialog selectionDialog(project);
1168 if (selectionDialog.exec() == QDialog::Accepted) {
1169 QWizard * const publishingWizard
1170 = selectionDialog.createSelectedWizard();
1171 publishingWizard->exec();
1172 delete publishingWizard;
1176 void ProjectExplorerPlugin::savePersistentSettings()
1179 qDebug()<<"ProjectExplorerPlugin::savePersistentSettings()";
1181 foreach (Project *pro, d->m_session->projects())
1182 pro->saveSettings();
1184 if (d->m_session->isDefaultVirgin()) {
1185 // do not save new virgin default sessions
1187 d->m_session->save();
1190 QSettings *s = Core::ICore::instance()->settings();
1192 s->setValue("ProjectExplorer/StartupSession", d->m_session->currentSession());
1193 s->remove("ProjectExplorer/RecentProjects/Files");
1195 QStringList fileNames;
1196 QStringList displayNames;
1197 QList<QPair<QString, QString> >::const_iterator it, end;
1198 end = d->m_recentProjects.constEnd();
1199 for (it = d->m_recentProjects.constBegin(); it != end; ++it) {
1200 fileNames << (*it).first;
1201 displayNames << (*it).second;
1204 s->setValue("ProjectExplorer/RecentProjects/FileNames", fileNames);
1205 s->setValue("ProjectExplorer/RecentProjects/DisplayNames", displayNames);
1207 s->setValue("ProjectExplorer/Settings/BuildBeforeDeploy", d->m_projectExplorerSettings.buildBeforeDeploy);
1208 s->setValue("ProjectExplorer/Settings/DeployBeforeRun", d->m_projectExplorerSettings.deployBeforeRun);
1209 s->setValue("ProjectExplorer/Settings/SaveBeforeBuild", d->m_projectExplorerSettings.saveBeforeBuild);
1210 s->setValue("ProjectExplorer/Settings/ShowCompilerOutput", d->m_projectExplorerSettings.showCompilerOutput);
1211 s->setValue("ProjectExplorer/Settings/ShowRunOutput", d->m_projectExplorerSettings.showRunOutput);
1212 s->setValue("ProjectExplorer/Settings/CleanOldAppOutput", d->m_projectExplorerSettings.cleanOldAppOutput);
1213 s->setValue("ProjectExplorer/Settings/MergeStdErrAndStdOut", d->m_projectExplorerSettings.mergeStdErrAndStdOut);
1214 s->setValue("ProjectExplorer/Settings/WrapAppOutput", d->m_projectExplorerSettings.wrapAppOutput);
1215 s->setValue("ProjectExplorer/Settings/UseJom", d->m_projectExplorerSettings.useJom);
1216 s->setValue("ProjectExplorer/Settings/AutoRestoreLastSession", d->m_projectExplorerSettings.autorestoreLastSession);
1217 s->setValue("ProjectExplorer/Settings/PromptToStopRunControl", d->m_projectExplorerSettings.prompToStopRunControl);
1218 s->setValue("ProjectExplorer/Settings/MaxAppOutputLines", d->m_projectExplorerSettings.maxAppOutputLines);
1219 s->setValue("ProjectExplorer/Settings/EnvironmentId", d->m_projectExplorerSettings.environmentId.toString());
1223 bool ProjectExplorerPlugin::openProject(const QString &fileName)
1226 qDebug() << "ProjectExplorerPlugin::openProject";
1228 QList<Project *> list = openProjects(QStringList() << fileName);
1229 if (!list.isEmpty()) {
1230 addToRecentProjects(fileName, list.first()->displayName());
1231 d->m_session->setStartupProject(list.first());
1237 static inline QList<IProjectManager*> allProjectManagers()
1239 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
1240 return pm->getObjects<IProjectManager>();
1243 QList<Project *> ProjectExplorerPlugin::openProjects(const QStringList &fileNames)
1246 qDebug() << "ProjectExplorerPlugin - opening projects " << fileNames;
1248 const QList<IProjectManager*> projectManagers = allProjectManagers();
1250 QList<Project*> openedPro;
1251 foreach (const QString &fileName, fileNames) {
1252 if (const Core::MimeType mt = Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName))) {
1253 foreach (IProjectManager *manager, projectManagers) {
1254 if (manager->mimeType() == mt.type()) {
1255 if (Project *pro = manager->openProject(fileName)) {
1256 if (pro->restoreSettings()) {
1257 connect(pro, SIGNAL(fileListChanged()), this, SIGNAL(fileListChanged()));
1258 d->m_session->addProject(pro);
1259 // Make sure we always have a current project / node
1260 if (!d->m_currentProject && !openedPro.isEmpty())
1261 setCurrentNode(pro->rootProjectNode());
1267 d->m_session->reportProjectLoadingProgress();
1275 if (!openedPro.isEmpty())
1276 Core::ModeManager::instance()->activateMode(Core::Constants::MODE_EDIT);
1281 Project *ProjectExplorerPlugin::currentProject() const
1284 if (d->m_currentProject)
1285 qDebug() << "ProjectExplorerPlugin::currentProject returns " << d->m_currentProject->displayName();
1287 qDebug() << "ProjectExplorerPlugin::currentProject returns 0";
1289 return d->m_currentProject;
1292 Node *ProjectExplorerPlugin::currentNode() const
1294 return d->m_currentNode;
1297 void ProjectExplorerPlugin::setCurrentFile(Project *project, const QString &filePath)
1299 setCurrent(project, filePath, 0);
1302 void ProjectExplorerPlugin::setCurrentFile(const QString &filePath)
1304 Project *project = d->m_session->projectForFile(filePath);
1305 // If the file is not in any project, stay with the current project
1306 // e.g. on opening a git diff buffer, git log buffer, we don't change the project
1307 // I'm not 100% sure this is correct
1309 project = d->m_currentProject;
1310 setCurrent(project, filePath, 0);
1313 void ProjectExplorerPlugin::setCurrentNode(Node *node)
1315 setCurrent(d->m_session->projectForNode(node), QString(), node);
1318 SessionManager *ProjectExplorerPlugin::session() const
1320 return d->m_session;
1323 Project *ProjectExplorerPlugin::startupProject() const
1326 qDebug() << "ProjectExplorerPlugin::startupProject";
1328 return d->m_session->startupProject();
1331 void ProjectExplorerPlugin::updateWelcomePage()
1333 d->m_welcomePage->reloadWelcomeScreenData();
1336 void ProjectExplorerPlugin::currentModeChanged(Core::IMode *mode, Core::IMode *oldMode)
1338 if (mode && mode->id() == Core::Id(Core::Constants::MODE_WELCOME))
1339 updateWelcomePage();
1340 if (oldMode == d->m_projectsMode)
1341 savePersistentSettings();
1344 void ProjectExplorerPlugin::determineSessionToRestoreAtStartup()
1346 QStringList arguments = ExtensionSystem::PluginManager::instance()->arguments();
1347 // Process command line arguments first:
1348 if (arguments.contains("-lastsession"))
1349 d->m_sessionToRestoreAtStartup = d->m_session->lastSession();
1350 if (d->m_sessionToRestoreAtStartup.isNull()) {
1351 QStringList sessions = d->m_session->sessions();
1352 // We have command line arguments, try to find a session in them
1353 // Default to no session loading
1354 foreach (const QString &arg, arguments) {
1355 if (sessions.contains(arg)) {
1357 d->m_sessionToRestoreAtStartup = arg;
1362 // Handle settings only after command line arguments:
1363 if (d->m_sessionToRestoreAtStartup.isNull()
1364 && d->m_projectExplorerSettings.autorestoreLastSession)
1365 d->m_sessionToRestoreAtStartup = d->m_session->lastSession();
1367 if (!d->m_sessionToRestoreAtStartup.isNull())
1368 Core::ICore::instance()->modeManager()->activateMode(Core::Constants::MODE_EDIT);
1372 \fn void ProjectExplorerPlugin::restoreSession()
1374 This method is connected to the ICore::coreOpened signal. If
1375 there was no session explicitly loaded, it creates an empty new
1376 default session and puts the list of recent projects and sessions
1377 onto the welcome page.
1379 void ProjectExplorerPlugin::restoreSession()
1382 qDebug() << "ProjectExplorerPlugin::restoreSession";
1384 // We have command line arguments, try to find a session in them
1385 QStringList arguments = ExtensionSystem::PluginManager::instance()->arguments();
1386 arguments.removeOne(d->m_sessionToRestoreAtStartup);
1388 // Restore latest session or what was passed on the command line
1389 if (d->m_sessionToRestoreAtStartup.isEmpty()) {
1390 d->m_session->createAndLoadNewDefaultSession();
1392 d->m_session->loadSession(d->m_sessionToRestoreAtStartup);
1395 // update welcome page
1396 Core::ModeManager *modeManager = Core::ModeManager::instance();
1397 connect(modeManager, SIGNAL(currentModeChanged(Core::IMode*, Core::IMode*)),
1398 this, SLOT(currentModeChanged(Core::IMode*, Core::IMode*)));
1399 connect(d->m_welcomePage, SIGNAL(requestSession(QString)), this, SLOT(loadSession(QString)));
1400 connect(d->m_welcomePage, SIGNAL(requestProject(QString)), this, SLOT(openProject(QString)));
1402 QStringList combinedList;
1403 // Converts "filename" "+45" or "filename" ":23"
1404 // into "filename+45" and "filename:23"
1405 foreach (const QString &str, arguments) {
1406 if (!combinedList.isEmpty() && (str.startsWith(QLatin1Char('+'))
1407 || str.startsWith(QLatin1Char(':')))) {
1408 combinedList.last().append(str);
1410 combinedList << str;
1414 Core::ICore::instance()->openFiles(combinedList, Core::ICore::OpenFilesFlags(Core::ICore::CanContainLineNumbers | Core::ICore::SwitchMode));
1419 void ProjectExplorerPlugin::loadSession(const QString &session)
1422 qDebug() << "ProjectExplorerPlugin::loadSession" << session;
1423 d->m_session->loadSession(session);
1427 void ProjectExplorerPlugin::showContextMenu(QWidget *view, const QPoint &globalPos, Node *node)
1429 QMenu *contextMenu = 0;
1432 node = d->m_session->sessionNode();
1434 if (node->nodeType() != SessionNodeType) {
1435 Project *project = d->m_session->projectForNode(node);
1436 setCurrentNode(node);
1438 emit aboutToShowContextMenu(project, node);
1439 switch (node->nodeType()) {
1440 case ProjectNodeType:
1441 if (node->parentFolderNode() == d->m_session->sessionNode())
1442 contextMenu = d->m_projectMenu;
1444 contextMenu = d->m_subProjectMenu;
1446 case FolderNodeType:
1447 contextMenu = d->m_folderMenu;
1450 populateOpenWithMenu();
1451 contextMenu = d->m_fileMenu;
1454 qWarning("ProjectExplorerPlugin::showContextMenu - Missing handler for node type");
1456 } else { // session item
1457 emit aboutToShowContextMenu(0, node);
1459 contextMenu = d->m_sessionContextMenu;
1462 updateContextMenuActions();
1463 d->m_projectTreeCollapseAllAction->disconnect(SIGNAL(triggered()));
1464 connect(d->m_projectTreeCollapseAllAction, SIGNAL(triggered()), view, SLOT(collapseAll()));
1465 if (contextMenu && contextMenu->actions().count() > 0) {
1466 contextMenu->popup(globalPos);
1470 BuildManager *ProjectExplorerPlugin::buildManager() const
1472 return d->m_buildManager;
1475 void ProjectExplorerPlugin::buildStateChanged(Project * pro)
1478 qDebug() << "buildStateChanged";
1479 qDebug() << pro->file()->fileName() << "isBuilding()" << d->m_buildManager->isBuilding(pro);
1485 void ProjectExplorerPlugin::executeRunConfiguration(RunConfiguration *runConfiguration, const QString &runMode)
1487 if (IRunControlFactory *runControlFactory = findRunControlFactory(runConfiguration, runMode)) {
1488 emit aboutToExecuteProject(runConfiguration->target()->project(), runMode);
1490 RunControl *control = runControlFactory->create(runConfiguration, runMode);
1493 startRunControl(control, runMode);
1497 void ProjectExplorerPlugin::startRunControl(RunControl *runControl, const QString &runMode)
1499 d->m_outputPane->createNewOutputWindow(runControl);
1500 if (runMode == ProjectExplorer::Constants::RUNMODE && d->m_projectExplorerSettings.showRunOutput)
1501 d->m_outputPane->popup(false);
1502 d->m_outputPane->showTabFor(runControl);
1503 connect(runControl, SIGNAL(finished()), this, SLOT(runControlFinished()));
1504 runControl->start();
1505 emit updateRunActions();
1508 QList<RunControl *> ProjectExplorerPlugin::runControls() const
1510 return d->m_outputPane->runControls();
1513 void ProjectExplorerPlugin::buildQueueFinished(bool success)
1516 qDebug() << "buildQueueFinished()" << success;
1520 if (success && d->m_delayedRunConfiguration) {
1521 executeRunConfiguration(d->m_delayedRunConfiguration, d->m_runMode);
1523 if (d->m_buildManager->tasksAvailable())
1524 d->m_buildManager->showTaskWindow();
1526 d->m_delayedRunConfiguration = 0;
1527 d->m_runMode.clear();
1530 void ProjectExplorerPlugin::setCurrent(Project *project, QString filePath, Node *node)
1533 qDebug() << "ProjectExplorer - setting path to " << (node ? node->path() : filePath)
1534 << " and project to " << (project ? project->displayName() : "0");
1537 filePath = node->path();
1539 node = d->m_session->nodeForFile(filePath, project);
1541 Core::ICore *core = Core::ICore::instance();
1543 bool projectChanged = false;
1544 if (d->m_currentProject != project) {
1545 Core::Context oldContext;
1546 Core::Context newContext;
1548 if (d->m_currentProject) {
1549 oldContext.add(d->m_currentProject->projectContext());
1550 oldContext.add(d->m_currentProject->projectLanguage());
1553 newContext.add(project->projectContext());
1554 newContext.add(project->projectLanguage());
1557 core->updateAdditionalContexts(oldContext, newContext);
1559 d->m_currentProject = project;
1561 projectChanged = true;
1564 if (projectChanged || d->m_currentNode != node) {
1565 d->m_currentNode = node;
1567 qDebug() << "ProjectExplorer - currentNodeChanged(" << (node ? node->path() : "0") << ", " << (project ? project->displayName() : "0") << ")";
1568 emit currentNodeChanged(d->m_currentNode, project);
1569 updateContextMenuActions();
1571 if (projectChanged) {
1573 qDebug() << "ProjectExplorer - currentProjectChanged(" << (project ? project->displayName() : "0") << ")";
1574 emit currentProjectChanged(project);
1578 core->fileManager()->setCurrentFile(filePath);
1581 void ProjectExplorerPlugin::updateActions()
1584 qDebug() << "ProjectExplorerPlugin::updateActions";
1586 QPair<bool, QString> buildActionState = buildSettingsEnabled(startupProject());
1587 QPair<bool, QString> buildActionContextState = buildSettingsEnabled(d->m_currentProject);
1588 QPair<bool, QString> buildSessionState = buildSettingsEnabledForSession();
1590 Project *project = startupProject();
1591 QString projectName = project ? project->displayName() : QString();
1592 QString projectNameContextMenu = d->m_currentProject ? d->m_currentProject->displayName() : QString();
1594 d->m_unloadAction->setParameter(projectNameContextMenu);
1597 d->m_buildAction->setParameter(projectName);
1598 d->m_rebuildAction->setParameter(projectName);
1599 d->m_cleanAction->setParameter(projectName);
1601 d->m_buildAction->setEnabled(buildActionState.first);
1602 d->m_rebuildAction->setEnabled(buildActionState.first);
1603 d->m_cleanAction->setEnabled(buildActionState.first);
1605 d->m_buildAction->setToolTip(buildActionState.second);
1606 d->m_rebuildAction->setToolTip(buildActionState.second);
1607 d->m_cleanAction->setToolTip(buildActionState.second);
1609 // Context menu actions
1610 d->m_buildActionContextMenu->setParameter(projectNameContextMenu);
1611 d->m_rebuildActionContextMenu->setParameter(projectNameContextMenu);
1612 d->m_cleanActionContextMenu->setParameter(projectNameContextMenu);
1614 d->m_buildActionContextMenu->setEnabled(buildActionContextState.first);
1615 d->m_rebuildActionContextMenu->setEnabled(buildActionContextState.first);
1616 d->m_cleanActionContextMenu->setEnabled(buildActionContextState.first);
1618 d->m_buildActionContextMenu->setToolTip(buildActionState.second);
1619 d->m_rebuildActionContextMenu->setToolTip(buildActionState.second);
1620 d->m_cleanActionContextMenu->setToolTip(buildActionState.second);
1622 // build project only
1623 d->m_buildProjectOnlyAction->setEnabled(buildActionState.first);
1624 d->m_rebuildProjectOnlyAction->setEnabled(buildActionState.first);
1625 d->m_cleanProjectOnlyAction->setEnabled(buildActionState.first);
1627 d->m_buildProjectOnlyAction->setToolTip(buildActionState.second);
1628 d->m_rebuildProjectOnlyAction->setToolTip(buildActionState.second);
1629 d->m_cleanProjectOnlyAction->setToolTip(buildActionState.second);
1632 d->m_clearSession->setEnabled(!d->m_session->projects().isEmpty());
1634 d->m_buildSessionAction->setEnabled(buildSessionState.first);
1635 d->m_rebuildSessionAction->setEnabled(buildSessionState.first);
1636 d->m_cleanSessionAction->setEnabled(buildSessionState.first);
1638 d->m_buildSessionAction->setToolTip(buildSessionState.second);
1639 d->m_rebuildSessionAction->setToolTip(buildSessionState.second);
1640 d->m_cleanSessionAction->setToolTip(buildSessionState.second);
1642 d->m_cancelBuildAction->setEnabled(d->m_buildManager->isBuilding());
1644 d->m_publishAction->setEnabled(!d->m_session->projects().isEmpty());
1646 d->m_projectSelectorAction->setEnabled(!session()->projects().isEmpty());
1647 d->m_projectSelectorActionMenu->setEnabled(!session()->projects().isEmpty());
1649 updateDeployActions();
1652 // NBS TODO check projectOrder()
1653 // what we want here is all the projects pro depends on
1654 QStringList ProjectExplorerPlugin::allFilesWithDependencies(Project *pro)
1657 qDebug() << "ProjectExplorerPlugin::allFilesWithDependencies(" << pro->file()->fileName() << ")";
1659 QStringList filesToSave;
1660 foreach (Project *p, d->m_session->projectOrder(pro)) {
1661 FindAllFilesVisitor filesVisitor;
1662 p->rootProjectNode()->accept(&filesVisitor);
1663 filesToSave << filesVisitor.filePaths();
1669 bool ProjectExplorerPlugin::saveModifiedFiles()
1672 qDebug() << "ProjectExplorerPlugin::saveModifiedFiles";
1674 QList<Core::IFile *> filesToSave = Core::ICore::instance()->fileManager()->modifiedFiles();
1675 if (!filesToSave.isEmpty()) {
1676 if (d->m_projectExplorerSettings.saveBeforeBuild) {
1677 Core::ICore::instance()->fileManager()->saveModifiedFilesSilently(filesToSave);
1679 bool cancelled = false;
1680 bool alwaysSave = false;
1682 Core::FileManager *fm = Core::ICore::instance()->fileManager();
1683 fm->saveModifiedFiles(filesToSave, &cancelled, QString(),
1684 tr("Always save files before build"), &alwaysSave);
1689 d->m_projectExplorerSettings.saveBeforeBuild = true;
1695 //NBS handle case where there is no activeBuildConfiguration
1696 // because someone delete all build configurations
1698 void ProjectExplorerPlugin::deploy(QList<Project *> projects)
1701 if (d->m_projectExplorerSettings.buildBeforeDeploy)
1702 steps << Constants::BUILDSTEPS_BUILD;
1703 steps << Constants::BUILDSTEPS_DEPLOY;
1704 queue(projects, steps);
1707 int ProjectExplorerPlugin::queue(QList<Project *> projects, QStringList stepIds)
1710 QStringList projectNames;
1711 foreach (const Project *p, projects)
1712 projectNames << p->displayName();
1713 qDebug() << "Building" << stepIds << "for projects" << projectNames;
1716 if (!saveModifiedFiles())
1719 QList<BuildStepList *> stepLists;
1720 foreach (const QString id, stepIds) {
1721 foreach (Project *pro, projects) {
1722 if (!pro || !pro->activeTarget())
1724 BuildStepList *bsl = 0;
1725 if (id == Core::Id(Constants::BUILDSTEPS_DEPLOY)
1726 && pro->activeTarget()->activeDeployConfiguration())
1727 bsl = pro->activeTarget()->activeDeployConfiguration()->stepList();
1728 else if (pro->activeTarget()->activeBuildConfiguration())
1729 bsl = pro->activeTarget()->activeBuildConfiguration()->stepList(id);
1731 if (!bsl || bsl->isEmpty())
1737 if (stepLists.isEmpty())
1739 if (!d->m_buildManager->buildLists(stepLists))
1741 return stepLists.count();
1744 void ProjectExplorerPlugin::buildProjectOnly()
1746 queue(QList<Project *>() << session()->startupProject(), QStringList() << Constants::BUILDSTEPS_BUILD);
1749 void ProjectExplorerPlugin::buildProject(ProjectExplorer::Project *p)
1751 queue(d->m_session->projectOrder(p),
1752 QStringList() << Constants::BUILDSTEPS_BUILD);
1755 void ProjectExplorerPlugin::buildProject()
1757 queue(d->m_session->projectOrder(session()->startupProject()),
1758 QStringList() << Constants::BUILDSTEPS_BUILD);
1761 void ProjectExplorerPlugin::buildProjectContextMenu()
1763 queue(d->m_session->projectOrder(d->m_currentProject),
1764 QStringList() << Constants::BUILDSTEPS_BUILD);
1767 void ProjectExplorerPlugin::buildSession()
1769 queue(d->m_session->projectOrder(),
1770 QStringList() << Constants::BUILDSTEPS_BUILD);
1773 void ProjectExplorerPlugin::rebuildProjectOnly()
1775 queue(QList<Project *>() << session()->startupProject(),
1776 QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_BUILD);
1779 void ProjectExplorerPlugin::rebuildProject()
1781 queue(d->m_session->projectOrder(session()->startupProject()),
1782 QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_BUILD);
1785 void ProjectExplorerPlugin::rebuildProjectContextMenu()
1787 queue(d->m_session->projectOrder(d->m_currentProject),
1788 QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_BUILD);
1791 void ProjectExplorerPlugin::rebuildSession()
1793 queue(d->m_session->projectOrder(),
1794 QStringList() << Constants::BUILDSTEPS_CLEAN << Constants::BUILDSTEPS_BUILD);
1797 void ProjectExplorerPlugin::deployProjectOnly()
1799 deploy(QList<Project *>() << session()->startupProject());
1802 void ProjectExplorerPlugin::deployProject()
1804 deploy(d->m_session->projectOrder(session()->startupProject()));
1807 void ProjectExplorerPlugin::deployProjectContextMenu()
1809 deploy(d->m_session->projectOrder(d->m_currentProject));
1812 void ProjectExplorerPlugin::deploySession()
1814 deploy(d->m_session->projectOrder());
1817 void ProjectExplorerPlugin::cleanProjectOnly()
1819 queue(QList<Project *>() << session()->startupProject(),
1820 QStringList() << Constants::BUILDSTEPS_CLEAN);
1823 void ProjectExplorerPlugin::cleanProject()
1825 queue(d->m_session->projectOrder(session()->startupProject()),
1826 QStringList() << Constants::BUILDSTEPS_CLEAN);
1829 void ProjectExplorerPlugin::cleanProjectContextMenu()
1831 queue(d->m_session->projectOrder(d->m_currentProject),
1832 QStringList() << Constants::BUILDSTEPS_CLEAN);
1835 void ProjectExplorerPlugin::cleanSession()
1837 queue(d->m_session->projectOrder(),
1838 QStringList() << Constants::BUILDSTEPS_CLEAN);
1841 void ProjectExplorerPlugin::runProject()
1843 runProject(startupProject(), ProjectExplorer::Constants::RUNMODE);
1846 void ProjectExplorerPlugin::runProjectContextMenu()
1848 ProjectNode *projectNode = qobject_cast<ProjectNode*>(d->m_currentNode);
1849 if (projectNode == d->m_currentProject->rootProjectNode() || !projectNode) {
1850 runProject(d->m_currentProject, ProjectExplorer::Constants::RUNMODE);
1852 QAction *act = qobject_cast<QAction *>(sender());
1855 RunConfiguration *rc = act->data().value<RunConfiguration *>();
1858 runRunConfiguration(rc, ProjectExplorer::Constants::RUNMODE);
1862 bool ProjectExplorerPlugin::hasBuildSettings(Project *pro)
1864 const QList<Project *> & projects = d->m_session->projectOrder(pro);
1865 foreach(Project *project, projects)
1867 && project->activeTarget()
1868 && project->activeTarget()->activeBuildConfiguration())
1873 QPair<bool, QString> ProjectExplorerPlugin::buildSettingsEnabled(Project *pro)
1875 QPair<bool, QString> result;
1876 result.first = true;
1878 result.first = false;
1879 result.second = tr("No project loaded");
1880 } else if (d->m_buildManager->isBuilding(pro)) {
1881 result.first = false;
1882 result.second = tr("Currently building the active project");
1883 } else if (!hasBuildSettings(pro)) {
1884 result.first = false;
1885 result.second = tr("Project has no build settings");
1887 const QList<Project *> & projects = d->m_session->projectOrder(pro);
1888 foreach(Project *project, projects) {
1890 && project->activeTarget()
1891 && project->activeTarget()->activeBuildConfiguration()
1892 && !project->activeTarget()->activeBuildConfiguration()->isEnabled()) {
1893 result.first = false;
1894 result.second += tr("Building '%1' is disabled: %2<br>")
1895 .arg(project->displayName(),
1896 project->activeTarget()->activeBuildConfiguration()->disabledReason());
1903 QPair<bool, QString> ProjectExplorerPlugin::buildSettingsEnabledForSession()
1905 QPair<bool, QString> result;
1906 result.first = true;
1907 if (d->m_session->projects().isEmpty()) {
1908 result.first = false;
1909 result.second = tr("No project loaded");
1910 } else if (d->m_buildManager->isBuilding()) {
1911 result.first = false;
1912 result.second = tr("A build is in progress");
1913 } else if (!hasBuildSettings(0)) {
1914 result.first = false;
1915 result.second = tr("Project has no build settings");
1917 const QList<Project *> & projects = d->m_session->projectOrder(0);
1918 foreach(Project *project, projects) {
1920 && project->activeTarget()
1921 && project->activeTarget()->activeBuildConfiguration()
1922 && !project->activeTarget()->activeBuildConfiguration()->isEnabled()) {
1923 result.first = false;
1924 result.second += tr("Building '%1' is disabled: %2\n")
1925 .arg(project->displayName(),
1926 project->activeTarget()->activeBuildConfiguration()->disabledReason());
1933 bool ProjectExplorerPlugin::coreAboutToClose()
1935 if (d->m_buildManager->isBuilding()) {
1937 QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Close"), QMessageBox::AcceptRole);
1938 QPushButton *cancelClose = box.addButton(tr("Do Not Close"), QMessageBox::RejectRole);
1939 box.setDefaultButton(cancelClose);
1940 box.setWindowTitle(tr("Close Qt Creator?"));
1941 box.setText(tr("A project is currently being built."));
1942 box.setInformativeText(tr("Do you want to cancel the build process and close Qt Creator anyway?"));
1944 if (box.clickedButton() != closeAnyway)
1947 if (!d->m_outputPane->aboutToClose())
1952 bool ProjectExplorerPlugin::hasDeploySettings(Project *pro)
1954 const QList<Project *> & projects = d->m_session->projectOrder(pro);
1955 foreach(Project *project, projects)
1956 if (project->activeTarget()->activeDeployConfiguration() &&
1957 !project->activeTarget()->activeDeployConfiguration()->stepList()->isEmpty())
1962 void ProjectExplorerPlugin::runProject(Project *pro, const QString &mode)
1967 runRunConfiguration(pro->activeTarget()->activeRunConfiguration(), mode);
1970 void ProjectExplorerPlugin::runRunConfiguration(ProjectExplorer::RunConfiguration *rc, const QString &mode)
1972 if (!rc->isEnabled())
1975 QStringList stepIds;
1976 if (d->m_projectExplorerSettings.deployBeforeRun) {
1977 if (d->m_projectExplorerSettings.buildBeforeDeploy)
1978 stepIds << Constants::BUILDSTEPS_BUILD;
1979 stepIds << Constants::BUILDSTEPS_DEPLOY;
1982 Project *pro = rc->target()->project();
1983 const QList<Project *> &projects = d->m_session->projectOrder(pro);
1984 int queueCount = queue(projects, stepIds);
1986 if (queueCount < 0) // something went wrong
1989 if (queueCount > 0) {
1990 // delay running till after our queued steps were processed
1991 d->m_runMode = mode;
1992 d->m_delayedRunConfiguration = rc;
1994 executeRunConfiguration(rc, mode);
1996 emit updateRunActions();
1999 void ProjectExplorerPlugin::runControlFinished()
2001 emit updateRunActions();
2004 void ProjectExplorerPlugin::projectAdded(ProjectExplorer::Project *pro)
2006 // more specific action en and disabling ?
2007 connect(pro, SIGNAL(buildConfigurationEnabledChanged()),
2008 this, SLOT(updateActions()));
2011 void ProjectExplorerPlugin::projectRemoved(ProjectExplorer::Project * pro)
2013 // more specific action en and disabling ?
2014 disconnect(pro, SIGNAL(buildConfigurationEnabledChanged()),
2015 this, SLOT(updateActions()));
2018 void ProjectExplorerPlugin::startupProjectChanged()
2020 static QPointer<Project> previousStartupProject = 0;
2021 Project *project = startupProject();
2022 if (project == previousStartupProject)
2025 if (d->m_projectsMode)
2026 d->m_projectsMode->setEnabled(project);
2028 if (previousStartupProject) {
2029 disconnect(previousStartupProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
2030 this, SLOT(activeTargetChanged()));
2033 previousStartupProject = project;
2036 connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
2037 this, SLOT(activeTargetChanged()));
2040 activeTargetChanged();
2043 void ProjectExplorerPlugin::activeTargetChanged()
2045 static QPointer<Target> previousTarget = 0;
2047 if (startupProject())
2048 target = startupProject()->activeTarget();
2049 if (target == previousTarget)
2052 if (previousTarget) {
2053 disconnect(previousTarget, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
2054 this, SLOT(activeRunConfigurationChanged()));
2056 previousTarget = target;
2058 connect(target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
2059 this, SLOT(activeRunConfigurationChanged()));
2062 updateDeployActions();
2063 activeRunConfigurationChanged();
2066 void ProjectExplorerPlugin::activeRunConfigurationChanged()
2068 static QPointer<RunConfiguration> previousRunConfiguration = 0;
2069 RunConfiguration *rc = 0;
2070 if (startupProject() && startupProject()->activeTarget())
2071 rc = startupProject()->activeTarget()->activeRunConfiguration();
2072 if (rc == previousRunConfiguration)
2074 if (previousRunConfiguration) {
2075 disconnect(previousRunConfiguration, SIGNAL(isEnabledChanged(bool)),
2076 this, SIGNAL(updateRunActions()));
2077 disconnect(previousRunConfiguration, SIGNAL(debuggersChanged()),
2078 this, SIGNAL(updateRunActions()));
2080 previousRunConfiguration = rc;
2082 connect(rc, SIGNAL(isEnabledChanged(bool)),
2083 this, SIGNAL(updateRunActions()));
2084 connect(rc, SIGNAL(debuggersChanged()),
2085 this, SIGNAL(updateRunActions()));
2087 emit updateRunActions();
2090 // NBS TODO implement more than one runner
2091 IRunControlFactory *ProjectExplorerPlugin::findRunControlFactory(RunConfiguration *config, const QString &mode)
2093 ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
2094 const QList<IRunControlFactory *> factories = pm->getObjects<IRunControlFactory>();
2095 foreach (IRunControlFactory *f, factories)
2096 if (f->canRun(config, mode))
2101 void ProjectExplorerPlugin::updateDeployActions()
2103 Project *project = startupProject();
2105 bool enableDeployActions = project
2106 && ! (d->m_buildManager->isBuilding(project))
2107 && hasDeploySettings(project);
2108 bool enableDeployActionsContextMenu = d->m_currentProject
2109 && ! (d->m_buildManager->isBuilding(d->m_currentProject))
2110 && hasDeploySettings(d->m_currentProject);
2112 if (d->m_projectExplorerSettings.buildBeforeDeploy) {
2113 if (hasBuildSettings(project)
2114 && !buildSettingsEnabled(project).first)
2115 enableDeployActions = false;
2116 if (hasBuildSettings(d->m_currentProject)
2117 && !buildSettingsEnabled(d->m_currentProject).first)
2118 enableDeployActionsContextMenu = false;
2121 const QString projectName = project ? project->displayName() : QString();
2122 const QString projectNameContextMenu = d->m_currentProject ? d->m_currentProject->displayName() : QString();
2123 bool hasProjects = !d->m_session->projects().isEmpty();
2124 bool building = d->m_buildManager->isBuilding();
2126 d->m_deployAction->setParameter(projectName);
2127 d->m_deployAction->setEnabled(enableDeployActions);
2129 d->m_deployActionContextMenu->setParameter(projectNameContextMenu);
2130 d->m_deployActionContextMenu->setEnabled(enableDeployActionsContextMenu);
2132 d->m_deployProjectOnlyAction->setEnabled(enableDeployActions);
2134 d->m_deploySessionAction->setEnabled(hasProjects && !building);
2136 emit updateRunActions();
2139 bool ProjectExplorerPlugin::canRun(Project *project, const QString &runMode)
2142 !project->activeTarget() ||
2143 !project->activeTarget()->activeRunConfiguration()) {
2147 if (d->m_projectExplorerSettings.buildBeforeDeploy
2148 && d->m_projectExplorerSettings.deployBeforeRun
2149 && hasBuildSettings(project)
2150 && !buildSettingsEnabled(project).first)
2154 RunConfiguration *activeRC = project->activeTarget()->activeRunConfiguration();
2156 bool canRun = findRunControlFactory(activeRC, runMode)
2157 && activeRC->isEnabled();
2158 const bool building = d->m_buildManager->isBuilding();
2159 return (canRun && !building);
2162 QString ProjectExplorerPlugin::cannotRunReason(Project *project, const QString &runMode)
2165 return tr("No active project");
2167 if (!project->activeTarget())
2168 return tr("The project '%1' has no active target").arg(project->displayName());
2170 if (!project->activeTarget()->activeRunConfiguration())
2171 return tr("The target '%1' for project '%2' has no active run configuration")
2172 .arg(project->activeTarget()->displayName(), project->displayName());
2175 if (d->m_projectExplorerSettings.buildBeforeDeploy
2176 && d->m_projectExplorerSettings.deployBeforeRun
2177 && hasBuildSettings(project)) {
2178 QPair<bool, QString> buildState = buildSettingsEnabled(project);
2179 if (!buildState.first)
2180 return buildState.second;
2184 RunConfiguration *activeRC = project->activeTarget()->activeRunConfiguration();
2185 if (!activeRC->isEnabled())
2186 return activeRC->disabledReason();
2188 // shouldn't actually be shown to the user...
2189 if (!findRunControlFactory(activeRC, runMode))
2190 return tr("Cannot run '%1' in mode '%2'.")
2191 .arg(activeRC->displayName(), runMode);
2194 if (d->m_buildManager->isBuilding())
2195 return tr("A build is still in progress.");
2199 void ProjectExplorerPlugin::slotUpdateRunActions()
2201 Project *project = startupProject();
2202 d->m_runAction->setEnabled(canRun(project, ProjectExplorer::Constants::RUNMODE));
2203 d->m_runAction->setToolTip(cannotRunReason(project, ProjectExplorer::Constants::RUNMODE));
2206 void ProjectExplorerPlugin::cancelBuild()
2209 qDebug() << "ProjectExplorerPlugin::cancelBuild";
2211 if (d->m_buildManager->isBuilding())
2212 d->m_buildManager->cancel();
2215 void ProjectExplorerPlugin::addToRecentProjects(const QString &fileName, const QString &displayName)
2218 qDebug() << "ProjectExplorerPlugin::addToRecentProjects(" << fileName << ")";
2220 if (fileName.isEmpty())
2222 QString prettyFileName(QDir::toNativeSeparators(fileName));
2224 QList<QPair<QString, QString> >::iterator it;
2225 for(it = d->m_recentProjects.begin(); it != d->m_recentProjects.end();)
2226 if ((*it).first == prettyFileName)
2227 it = d->m_recentProjects.erase(it);
2231 if (d->m_recentProjects.count() > d->m_maxRecentProjects)
2232 d->m_recentProjects.removeLast();
2233 d->m_recentProjects.prepend(qMakePair(prettyFileName, displayName));
2234 QFileInfo fi(prettyFileName);
2235 d->m_lastOpenDirectory = fi.absolutePath();
2236 emit recentProjectsChanged();
2239 void ProjectExplorerPlugin::updateRecentProjectMenu()
2241 typedef QList<QPair<QString, QString> >::const_iterator StringPairListConstIterator;
2243 qDebug() << "ProjectExplorerPlugin::updateRecentProjectMenu";
2245 Core::ActionContainer *aci =
2246 Core::ICore::instance()->actionManager()->actionContainer(Constants::M_RECENTPROJECTS);
2247 QMenu *menu = aci->menu();
2250 bool hasRecentProjects = false;
2251 //projects (ignore sessions, they used to be in this list)
2252 const StringPairListConstIterator end = d->m_recentProjects.constEnd();
2253 for (StringPairListConstIterator it = d->m_recentProjects.constBegin(); it != end; ++it) {
2254 const QPair<QString, QString> &s = *it;
2255 if (s.first.endsWith(QLatin1String(".qws")))
2257 QAction *action = menu->addAction(Utils::withTildeHomePath(s.first));
2258 action->setData(s.first);
2259 connect(action, SIGNAL(triggered()), this, SLOT(openRecentProject()));
2260 hasRecentProjects = true;
2262 menu->setEnabled(hasRecentProjects);
2264 // add the Clear Menu item
2265 if (hasRecentProjects) {
2266 menu->addSeparator();
2267 QAction *action = menu->addAction(QCoreApplication::translate(
2268 "Core", Core::Constants::TR_CLEAR_MENU));
2269 connect(action, SIGNAL(triggered()), this, SLOT(clearRecentProjects()));
2271 emit recentProjectsChanged();
2274 void ProjectExplorerPlugin::clearRecentProjects()
2276 d->m_recentProjects.clear();
2277 updateWelcomePage();
2280 void ProjectExplorerPlugin::openRecentProject()
2283 qDebug() << "ProjectExplorerPlugin::openRecentProject()";
2285 QAction *a = qobject_cast<QAction*>(sender());
2288 QString fileName = a->data().toString();
2289 if (!fileName.isEmpty()) {
2290 openProject(fileName);
2294 void ProjectExplorerPlugin::invalidateProject(Project *project)
2297 qDebug() << "ProjectExplorerPlugin::invalidateProject" << project->displayName();
2298 if (d->m_currentProject == project) {
2300 // Workaround for a bug in QItemSelectionModel
2301 // - currentChanged etc are not emitted if the
2302 // item is removed from the underlying data model
2304 setCurrent(0, QString(), 0);
2307 disconnect(project, SIGNAL(fileListChanged()), this, SIGNAL(fileListChanged()));
2311 void ProjectExplorerPlugin::updateContextMenuActions()
2313 d->m_addExistingFilesAction->setEnabled(false);
2314 d->m_addNewFileAction->setEnabled(false);
2315 d->m_addNewSubprojectAction->setEnabled(false);
2316 d->m_removeFileAction->setEnabled(false);
2317 d->m_deleteFileAction->setEnabled(false);
2318 d->m_renameFileAction->setEnabled(false);
2320 d->m_addExistingFilesAction->setVisible(true);
2321 d->m_removeFileAction->setVisible(true);
2322 d->m_deleteFileAction->setVisible(true);
2323 d->m_runActionContextMenu->setVisible(false);
2325 Core::ActionContainer *runMenu = Core::ICore::instance()->actionManager()->actionContainer(Constants::RUNMENUCONTEXTMENU);
2326 runMenu->menu()->clear();
2328 if (d->m_currentNode && d->m_currentNode->projectNode()) {
2329 QList<ProjectNode::ProjectAction> actions =
2330 d->m_currentNode->projectNode()->supportedActions(d->m_currentNode);
2332 if (ProjectNode *pn = qobject_cast<ProjectNode *>(d->m_currentNode)) {
2333 if (pn == d->m_currentProject->rootProjectNode()) {
2334 d->m_runActionContextMenu->setVisible(true);
2336 QList<RunConfiguration *> runConfigs = pn->runConfigurationsFor(pn);
2337 if (runConfigs.count() == 1) {
2338 d->m_runActionContextMenu->setVisible(true);
2339 d->m_runActionContextMenu->setData(QVariant::fromValue(runConfigs.first()));
2340 } else if (runConfigs.count() > 1) {
2341 foreach (RunConfiguration *rc, runConfigs) {
2342 QAction *act = new QAction(runMenu->menu());
2343 act->setData(QVariant::fromValue(rc));
2344 act->setText(QString("Run %1").arg(rc->displayName()));
2345 runMenu->menu()->addAction(act);
2346 connect(act, SIGNAL(triggered()),
2347 this, SLOT(runProjectContextMenu()));
2352 if (qobject_cast<FolderNode*>(d->m_currentNode)) {
2353 // Also handles ProjectNode
2354 d->m_addNewFileAction->setEnabled(actions.contains(ProjectNode::AddNewFile));
2355 d->m_addNewSubprojectAction->setEnabled(d->m_currentNode->nodeType() == ProjectNodeType
2356 && actions.contains(ProjectNode::AddSubProject));
2357 d->m_addExistingFilesAction->setEnabled(actions.contains(ProjectNode::AddExistingFile));
2358 d->m_renameFileAction->setEnabled(actions.contains(ProjectNode::Rename));
2359 } else if (qobject_cast<FileNode*>(d->m_currentNode)) {
2360 // Enable and show remove / delete in magic ways:
2361 // If both are disabled show Remove
2362 // If both are enabled show both (can't happen atm)
2363 // If only removeFile is enabled only show it
2364 // If only deleteFile is enable only show it
2365 bool enableRemove = actions.contains(ProjectNode::RemoveFile);
2366 d->m_removeFileAction->setEnabled(enableRemove);
2367 bool enableDelete = actions.contains(ProjectNode::EraseFile);
2368 d->m_deleteFileAction->setEnabled(enableDelete);
2369 d->m_deleteFileAction->setVisible(enableDelete);
2371 d->m_removeFileAction->setVisible(!enableDelete || enableRemove);
2372 d->m_renameFileAction->setEnabled(actions.contains(ProjectNode::Rename));
2377 QString pathOrDirectoryFor(Node *node, bool dir)
2379 QString path = node->path();
2381 FolderNode *folder = qobject_cast<FolderNode *>(node);
2382 if (path.contains("#") && folder) {
2383 // Virtual Folder case
2384 // If there are files directly below or no subfolders, take the folder path
2385 if (!folder->fileNodes().isEmpty() || folder->subFolderNodes().isEmpty()) {
2386 location = path.left(path.indexOf('#'));;
2388 // Otherwise we figure out a commonPath from the subfolders
2390 foreach (FolderNode *f, folder->subFolderNodes())
2391 list << f->path() + QLatin1Char('/');
2392 location = Utils::commonPath(list);
2397 location = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath();
2399 location = fi.absoluteFilePath();
2405 QString ProjectExplorerPlugin::pathFor(Node *node)
2407 return pathOrDirectoryFor(node, false);
2410 QString ProjectExplorerPlugin::directoryFor(Node *node)
2412 return pathOrDirectoryFor(node, true);
2415 void ProjectExplorerPlugin::addNewFile()
2417 QTC_ASSERT(d->m_currentNode, return)
2418 QString location = directoryFor(d->m_currentNode);
2420 Core::ICore::instance()->showNewItemDialog(tr("New File", "Title of dialog"),
2421 Core::IWizard::wizardsOfKind(Core::IWizard::FileWizard)
2422 + Core::IWizard::wizardsOfKind(Core::IWizard::ClassWizard),
2426 void ProjectExplorerPlugin::addNewSubproject()
2428 QTC_ASSERT(d->m_currentNode, return)
2429 QString location = directoryFor(d->m_currentNode);
2431 if (d->m_currentNode->nodeType() == ProjectNodeType
2432 && d->m_currentNode->projectNode()->supportedActions(
2433 d->m_currentNode->projectNode()).contains(ProjectNode::AddSubProject)) {
2434 Core::ICore::instance()->showNewItemDialog(tr("New Subproject", "Title of dialog"),
2435 Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard),
2440 void ProjectExplorerPlugin::addExistingFiles()
2442 QTC_ASSERT(d->m_currentNode, return)
2444 QStringList fileNames = QFileDialog::getOpenFileNames(Core::ICore::instance()->mainWindow(),
2445 tr("Add Existing Files"), directoryFor(d->m_currentNode));
2446 if (fileNames.isEmpty())
2448 addExistingFiles(fileNames);
2451 void ProjectExplorerPlugin::addExistingFiles(const QStringList &filePaths)
2453 ProjectNode *projectNode = qobject_cast<ProjectNode*>(d->m_currentNode->projectNode());
2454 addExistingFiles(projectNode, filePaths);
2457 void ProjectExplorerPlugin::addExistingFiles(ProjectNode *projectNode, const QStringList &filePaths)
2459 Core::ICore *core = Core::ICore::instance();
2460 const QString dir = directoryFor(projectNode);
2461 QStringList fileNames = filePaths;
2462 QHash<FileType, QString> fileTypeToFiles;
2463 foreach (const QString &fileName, fileNames) {
2464 FileType fileType = typeForFileName(core->mimeDatabase(), QFileInfo(fileName));
2465 fileTypeToFiles.insertMulti(fileType, fileName);
2468 QStringList notAdded;
2469 foreach (const FileType type, fileTypeToFiles.uniqueKeys()) {
2470 projectNode->addFiles(type, fileTypeToFiles.values(type), ¬Added);
2472 if (!notAdded.isEmpty()) {
2473 QString message = tr("Could not add following files to project %1:\n").arg(projectNode->displayName());
2474 QString files = notAdded.join("\n");
2475 QMessageBox::warning(core->mainWindow(), tr("Adding Files to Project Failed"),
2477 foreach (const QString &file, notAdded)
2478 fileNames.removeOne(file);
2481 if (Core::IVersionControl *vcManager = core->vcsManager()->findVersionControlForDirectory(dir))
2482 if (vcManager->supportsOperation(Core::IVersionControl::AddOperation)) {
2483 const QString files = fileNames.join(QString(QLatin1Char('\n')));
2484 QMessageBox::StandardButton button =
2485 QMessageBox::question(core->mainWindow(), tr("Add to Version Control"),
2486 tr("Add files\n%1\nto version control (%2)?").arg(files, vcManager->displayName()),
2487 QMessageBox::Yes | QMessageBox::No);
2488 if (button == QMessageBox::Yes) {
2489 QStringList notAddedToVc;
2490 foreach (const QString &file, fileNames) {
2491 if (!vcManager->vcsAdd(file))
2492 notAddedToVc << file;
2495 if (!notAddedToVc.isEmpty()) {
2496 const QString message = tr("Could not add following files to version control (%1)\n").arg(vcManager->displayName());
2497 const QString filesNotAdded = notAddedToVc.join(QString(QLatin1Char('\n')));
2498 QMessageBox::warning(core->mainWindow(), tr("Adding to Version Control Failed"),
2499 message + filesNotAdded);
2505 void ProjectExplorerPlugin::removeProject()
2507 ProjectNode *subProjectNode = qobject_cast<ProjectNode*>(d->m_currentNode->projectNode());
2508 ProjectNode *projectNode = qobject_cast<ProjectNode *>(subProjectNode->parentFolderNode());
2510 Core::ICore *core = Core::ICore::instance();
2511 RemoveFileDialog removeFileDialog(subProjectNode->path(), core->mainWindow());
2512 removeFileDialog.setDeleteFileVisible(false);
2513 if (removeFileDialog.exec() == QDialog::Accepted)
2514 projectNode->removeSubProjects(QStringList() << subProjectNode->path());
2518 void ProjectExplorerPlugin::openFile()
2520 QTC_ASSERT(d->m_currentNode, return)
2521 Core::EditorManager *em = Core::EditorManager::instance();
2522 em->openEditor(d->m_currentNode->path(), QString(), Core::EditorManager::ModeSwitch);
2525 void ProjectExplorerPlugin::showInGraphicalShell()
2527 QTC_ASSERT(d->m_currentNode, return)
2528 Core::Internal::FileUtils::showInGraphicalShell(Core::ICore::instance()->mainWindow(),
2529 pathFor(d->m_currentNode));
2532 void ProjectExplorerPlugin::openTerminalHere()
2534 QTC_ASSERT(d->m_currentNode, return)
2535 Core::Internal::FileUtils::openTerminal(directoryFor(d->m_currentNode));
2538 void ProjectExplorerPlugin::removeFile()
2540 QTC_ASSERT(d->m_currentNode && d->m_currentNode->nodeType() == FileNodeType, return)
2542 FileNode *fileNode = qobject_cast<FileNode*>(d->m_currentNode);
2543 Core::ICore *core = Core::ICore::instance();
2545 QString filePath = d->m_currentNode->path();
2546 RemoveFileDialog removeFileDialog(filePath, core->mainWindow());
2548 if (removeFileDialog.exec() == QDialog::Accepted) {
2549 const bool deleteFile = removeFileDialog.isDeleteFileChecked();
2551 // remove from project
2552 ProjectNode *projectNode = fileNode->projectNode();
2553 Q_ASSERT(projectNode);
2555 if (!projectNode->removeFiles(fileNode->fileType(), QStringList(filePath))) {
2556 QMessageBox::warning(core->mainWindow(), tr("Removing File Failed"),
2557 tr("Could not remove file %1 from project %2.").arg(filePath).arg(projectNode->displayName()));
2561 // remove from version control
2562 core->vcsManager()->promptToDelete(filePath);
2564 // remove from file system
2566 QFile file(filePath);
2568 if (file.exists()) {
2569 // could have been deleted by vc
2571 QMessageBox::warning(core->mainWindow(), tr("Deleting File Failed"),
2572 tr("Could not delete file %1.").arg(filePath));
2578 void ProjectExplorerPlugin::deleteFile()
2580 QTC_ASSERT(d->m_currentNode && d->m_currentNode->nodeType() == FileNodeType, return)
2582 FileNode *fileNode = qobject_cast<FileNode*>(d->m_currentNode);
2583 Core::ICore *core = Core::ICore::instance();
2585 QString filePath = d->m_currentNode->path();
2586 QMessageBox::StandardButton button =
2587 QMessageBox::question(core->mainWindow(),
2589 tr("Delete %1 from file system?").arg(filePath),
2590 QMessageBox::Yes | QMessageBox::No);
2591 if (button != QMessageBox::Yes)
2594 ProjectNode *projectNode = fileNode->projectNode();
2595 Q_ASSERT(projectNode);
2597 projectNode->deleteFiles(fileNode->fileType(), QStringList(filePath));
2599 core->fileManager()->expectFileChange(fileNode->path());
2600 if (Core::IVersionControl *vc =
2601 core->vcsManager()->findVersionControlForDirectory(QFileInfo(filePath).absolutePath())) {
2602 vc->vcsDelete(filePath);
2604 QFile file(filePath);
2605 if (file.exists()) {
2607 QMessageBox::warning(core->mainWindow(), tr("Deleting File Failed"),
2608 tr("Could not delete file %1.").arg(filePath));
2610 core->fileManager()->unexpectFileChange(fileNode->path());
2613 void ProjectExplorerPlugin::renameFile()
2615 QWidget *focusWidget = QApplication::focusWidget();
2616 while (focusWidget) {
2617 ProjectTreeWidget *treeWidget = qobject_cast<ProjectTreeWidget*>(focusWidget);
2619 treeWidget->editCurrentItem();
2622 focusWidget = focusWidget->parentWidget();
2626 void ProjectExplorerPlugin::renameFile(Node *node, const QString &to)
2628 FileNode *fileNode = qobject_cast<FileNode *>(node);
2631 QString orgFilePath = QFileInfo(node->path()).absoluteFilePath();
2632 QString dir = QFileInfo(orgFilePath).absolutePath();
2633 QString newFilePath = dir + QLatin1Char('/') + to;
2635 if (orgFilePath == newFilePath)
2638 Core::ICore *core = Core::ICore::instance();
2639 Core::IVersionControl *vc = core->vcsManager()->findVersionControlForDirectory(dir);
2641 bool result = false;
2642 if (vc && vc->supportsOperation(Core::IVersionControl::MoveOperation))
2643 result = vc->vcsMove(orgFilePath, newFilePath);
2644 if (!result) { // The moving via vcs failed or the vcs does not support moving, fall back
2645 QFile f(orgFilePath);
2646 if (!f.fileEngine()->caseSensitive()
2647 && orgFilePath.compare(newFilePath, Qt::CaseInsensitive) == 0) {
2648 // Due to QTBUG-3570
2649 result = f.fileEngine()->rename(newFilePath);
2651 result = QFile::rename(orgFilePath, newFilePath);
2655 // yeah we moved, tell the filemanager about it
2656 Core::ICore::instance()->fileManager()->renamedFile(orgFilePath, newFilePath);
2657 // Tell the project plugin about it
2658 ProjectNode *projectNode = fileNode->projectNode();
2659 projectNode->renameFile(fileNode->fileType(), orgFilePath, newFilePath);
2660 // TODO emit a signal?
2664 void ProjectExplorerPlugin::setStartupProject()
2666 setStartupProject(d->m_currentProject);
2669 void ProjectExplorerPlugin::populateOpenWithMenu(QMenu *menu, const QString &fileName)
2671 typedef QList<Core::IEditorFactory*> EditorFactoryList;
2672 typedef QList<Core::IExternalEditor*> ExternalEditorList;
2676 bool anyMatches = false;
2678 Core::ICore *core = Core::ICore::instance();
2679 if (const Core::MimeType mt = core->mimeDatabase()->findByFile(QFileInfo(fileName))) {
2680 const EditorFactoryList factories = core->editorManager()->editorFactories(mt, false);
2681 const ExternalEditorList externalEditors = core->editorManager()->externalEditors(mt, false);
2682 anyMatches = !factories.empty() || !externalEditors.empty();
2684 // Add all suitable editors
2685 foreach (Core::IEditorFactory *editorFactory, factories) {
2686 // Add action to open with this very editor factory
2687 QString const actionTitle = editorFactory->displayName();
2688 QAction * const action = menu->addAction(actionTitle);
2689 action->setData(qVariantFromValue(editorFactory));
2691 // Add all suitable external editors
2692 foreach (Core::IExternalEditor *externalEditor, externalEditors) {
2693 QAction * const action = menu->addAction(externalEditor->displayName());
2694 action->setData(qVariantFromValue(externalEditor));
2698 menu->setEnabled(anyMatches);
2701 void ProjectExplorerPlugin::populateOpenWithMenu()
2703 populateOpenWithMenu(d->m_openWithMenu, currentNode()->path());
2706 void ProjectExplorerPlugin::openWithMenuTriggered(QAction *action)
2709 qWarning() << "ProjectExplorerPlugin::openWithMenuTriggered no action, can't happen.";
2711 openEditorFromAction(action, currentNode()->path());
2714 void ProjectExplorerPlugin::openEditorFromAction(QAction *action, const QString &fileName)
2716 Core::EditorManager *em = Core::EditorManager::instance();
2717 const QVariant data = action->data();
2718 if (qVariantCanConvert<Core::IEditorFactory *>(data)) {
2719 Core::IEditorFactory *factory = qVariantValue<Core::IEditorFactory *>(data);
2721 // close any open editors that have this file open, but have a different type.
2722 QList<Core::IEditor *> editorsOpenForFile = em->editorsForFileName(fileName);
2723 if (!editorsOpenForFile.isEmpty()) {
2724 foreach (Core::IEditor *openEditor, editorsOpenForFile) {
2725 if (factory->id() == openEditor->id())
2726 editorsOpenForFile.removeAll(openEditor);
2728 if (!em->closeEditors(editorsOpenForFile)) // don't open if cancel was pressed
2732 em->openEditor(fileName, factory->id(), Core::EditorManager::ModeSwitch);
2735 if (qVariantCanConvert<Core::IExternalEditor *>(data)) {
2736 Core::IExternalEditor *externalEditor = qVariantValue<Core::IExternalEditor *>(data);
2737 em->openExternalEditor(fileName, externalEditor->id());
2741 void ProjectExplorerPlugin::updateSessionMenu()
2743 d->m_sessionMenu->clear();
2744 QActionGroup *ag = new QActionGroup(d->m_sessionMenu);
2745 connect(ag, SIGNAL(triggered(QAction *)), this, SLOT(setSession(QAction *)));
2746 const QString &activeSession = d->m_session->activeSession();
2747 foreach (const QString &session, d->m_session->sessions()) {
2748 QAction *act = ag->addAction(session);
2749 act->setCheckable(true);
2750 if (session == activeSession)
2751 act->setChecked(true);
2753 d->m_sessionMenu->addActions(ag->actions());
2754 d->m_sessionMenu->setEnabled(true);
2757 void ProjectExplorerPlugin::setSession(QAction *action)
2759 QString session = action->text();
2760 if (session != d->m_session->activeSession())
2761 d->m_session->loadSession(session);
2765 void ProjectExplorerPlugin::setProjectExplorerSettings(const Internal::ProjectExplorerSettings &pes)
2767 if (d->m_projectExplorerSettings == pes)
2769 d->m_projectExplorerSettings = pes;
2770 emit settingsChanged();
2773 Internal::ProjectExplorerSettings ProjectExplorerPlugin::projectExplorerSettings() const
2775 return d->m_projectExplorerSettings;
2778 QStringList ProjectExplorerPlugin::projectFilePatterns()
2780 QStringList patterns;
2781 const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase();
2782 foreach(const IProjectManager *pm, allProjectManagers())
2783 if (const Core::MimeType mt = mdb->findByType(pm->mimeType()))
2784 foreach(const Core::MimeGlobPattern &gp, mt.globPatterns())
2785 patterns += gp.regExp().pattern();
2789 void ProjectExplorerPlugin::openOpenProjectDialog()
2791 Core::FileManager *fileMananger = Core::ICore::instance()->fileManager();
2792 const QString path = fileMananger->useProjectsDirectory() ? fileMananger->projectsDirectory() : QString();
2793 const QStringList files = fileMananger->getOpenFileNames(d->m_projectFilterString, path);
2794 if (!files.isEmpty())
2795 Core::ICore::instance()->openFiles(files, Core::ICore::SwitchMode);
2798 QList<QPair<QString, QString> > ProjectExplorerPlugin::recentProjects()
2800 return d->m_recentProjects;
2803 Q_EXPORT_PLUGIN(ProjectExplorerPlugin)