aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/projectexplorer
diff options
context:
space:
mode:
authorTim Jenssen <tim.jenssen@qt.io>2023-06-02 21:23:26 +0200
committerTim Jenssen <tim.jenssen@qt.io>2023-06-02 19:26:05 +0000
commit002d84cb15e314a207346fdfd6cf78055d1b8b92 (patch)
treef3354186e1b3f7e80a2786acfaff6656eb7cdb09 /src/plugins/projectexplorer
parentbc6487068892be8c99404998c93dc6125551cf18 (diff)
parente759ce310fe6f30724f29b809bf0bcab1df88e1d (diff)
Merge remote-tracking branch 'origin/11.0' into qds/dev
Conflicts: src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp tests/auto/qml/qmlprojectmanager/fileformat/fileformat.qbs tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp Change-Id: I257f1908917bcc58805619b53b6866f2f73ca544
Diffstat (limited to 'src/plugins/projectexplorer')
-rw-r--r--src/plugins/projectexplorer/CMakeLists.txt14
-rw-r--r--src/plugins/projectexplorer/ProjectExplorer.json.in8
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.cpp21
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.h9
-rw-r--r--src/plugins/projectexplorer/allprojectsfilter.cpp56
-rw-r--r--src/plugins/projectexplorer/allprojectsfilter.h19
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.cpp6
-rw-r--r--src/plugins/projectexplorer/appoutputpane.cpp3
-rw-r--r--src/plugins/projectexplorer/buildaspects.cpp7
-rw-r--r--src/plugins/projectexplorer/buildaspects.h7
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.cpp43
-rw-r--r--src/plugins/projectexplorer/buildmanager.cpp26
-rw-r--r--src/plugins/projectexplorer/buildmanager.h9
-rw-r--r--src/plugins/projectexplorer/buildpropertiessettings.cpp73
-rw-r--r--src/plugins/projectexplorer/buildpropertiessettings.h26
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.cpp10
-rw-r--r--src/plugins/projectexplorer/buildstep.cpp58
-rw-r--r--src/plugins/projectexplorer/buildstep.h41
-rw-r--r--src/plugins/projectexplorer/buildsteplist.cpp10
-rw-r--r--src/plugins/projectexplorer/buildstepspage.cpp8
-rw-r--r--src/plugins/projectexplorer/buildsystem.cpp10
-rw-r--r--src/plugins/projectexplorer/buildsystem.h1
-rw-r--r--src/plugins/projectexplorer/codestylesettingspropertiespage.cpp7
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.cpp118
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.h24
-rw-r--r--src/plugins/projectexplorer/copystep.cpp114
-rw-r--r--src/plugins/projectexplorer/copystep.h22
-rw-r--r--src/plugins/projectexplorer/currentprojectfilter.cpp51
-rw-r--r--src/plugins/projectexplorer/currentprojectfilter.h23
-rw-r--r--src/plugins/projectexplorer/currentprojectfind.cpp13
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.cpp4
-rw-r--r--src/plugins/projectexplorer/customparserconfigdialog.cpp2
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp4
-rw-r--r--src/plugins/projectexplorer/dependenciespanel.cpp24
-rw-r--r--src/plugins/projectexplorer/desktoprunconfiguration.cpp9
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdevice.cpp118
-rw-r--r--src/plugins/projectexplorer/devicesupport/desktopdevice.h10
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp88
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.h14
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicemanager.cpp28
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp63
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicesettingswidget.h1
-rw-r--r--src/plugins/projectexplorer/devicesupport/devicetestdialog.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp14
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h15
-rw-r--r--src/plugins/projectexplorer/devicesupport/filetransfer.cpp41
-rw-r--r--src/plugins/projectexplorer/devicesupport/filetransfer.h12
-rw-r--r--src/plugins/projectexplorer/devicesupport/filetransferinterface.h8
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.cpp45
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevice.h22
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevicefactory.cpp27
-rw-r--r--src/plugins/projectexplorer/devicesupport/idevicefactory.h3
-rw-r--r--src/plugins/projectexplorer/devicesupport/localprocesslist.cpp59
-rw-r--r--src/plugins/projectexplorer/devicesupport/processlist.cpp61
-rw-r--r--src/plugins/projectexplorer/devicesupport/processlist.h (renamed from src/plugins/projectexplorer/devicesupport/localprocesslist.h)10
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp83
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h36
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshparameters.cpp33
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshparameters.h34
-rw-r--r--src/plugins/projectexplorer/editorconfiguration.cpp8
-rw-r--r--src/plugins/projectexplorer/editorsettingspropertiespage.cpp5
-rw-r--r--src/plugins/projectexplorer/environmentaspect.cpp27
-rw-r--r--src/plugins/projectexplorer/environmentaspect.h9
-rw-r--r--src/plugins/projectexplorer/environmentaspectwidget.cpp9
-rw-r--r--src/plugins/projectexplorer/extraabi.cpp17
-rw-r--r--src/plugins/projectexplorer/extracompiler.cpp90
-rw-r--r--src/plugins/projectexplorer/extracompiler.h20
-rw-r--r--src/plugins/projectexplorer/fileinsessionfinder.cpp12
-rw-r--r--src/plugins/projectexplorer/filesinallprojectsfind.cpp4
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.cpp23
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.h4
-rw-r--r--src/plugins/projectexplorer/ipotentialkit.h10
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp37
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp4
-rw-r--r--src/plugins/projectexplorer/kitchooser.cpp4
-rw-r--r--src/plugins/projectexplorer/kitinformation.cpp98
-rw-r--r--src/plugins/projectexplorer/kitmanager.cpp9
-rw-r--r--src/plugins/projectexplorer/kitmanager.h2
-rw-r--r--src/plugins/projectexplorer/kitmanagerconfigwidget.cpp49
-rw-r--r--src/plugins/projectexplorer/kitmanagerconfigwidget.h13
-rw-r--r--src/plugins/projectexplorer/kitmodel.cpp186
-rw-r--r--src/plugins/projectexplorer/kitoptionspage.cpp55
-rw-r--r--src/plugins/projectexplorer/kitoptionspage.h14
-rw-r--r--src/plugins/projectexplorer/localenvironmentaspect.cpp46
-rw-r--r--src/plugins/projectexplorer/localenvironmentaspect.h18
-rw-r--r--src/plugins/projectexplorer/makestep.cpp35
-rw-r--r--src/plugins/projectexplorer/makestep.h6
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp90
-rw-r--r--src/plugins/projectexplorer/msvcparser.cpp2
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp43
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.h11
-rw-r--r--src/plugins/projectexplorer/processparameters.cpp2
-rw-r--r--src/plugins/projectexplorer/processstep.cpp6
-rw-r--r--src/plugins/projectexplorer/project.cpp160
-rw-r--r--src/plugins/projectexplorer/project.h7
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.cpp13
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.h16
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp706
-rw-r--r--src/plugins/projectexplorer/projectexplorer.h4
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qbs18
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qrc8
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h6
-rw-r--r--src/plugins/projectexplorer/projectexplorersettings.cpp (renamed from src/plugins/projectexplorer/projectexplorersettingspage.cpp)57
-rw-r--r--src/plugins/projectexplorer/projectexplorersettings.h10
-rw-r--r--src/plugins/projectexplorer/projectexplorersettingspage.h29
-rw-r--r--src/plugins/projectexplorer/projectfilewizardextension.cpp5
-rw-r--r--src/plugins/projectexplorer/projectmanager.cpp768
-rw-r--r--src/plugins/projectexplorer/projectmanager.h69
-rw-r--r--src/plugins/projectexplorer/projectmodels.cpp24
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp58
-rw-r--r--src/plugins/projectexplorer/projectnodes.h10
-rw-r--r--src/plugins/projectexplorer/projectnodeshelper.h26
-rw-r--r--src/plugins/projectexplorer/projecttree.cpp22
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.cpp7
-rw-r--r--src/plugins/projectexplorer/projectwelcomepage.cpp11
-rw-r--r--src/plugins/projectexplorer/projectwelcomepage.h6
-rw-r--r--src/plugins/projectexplorer/projectwindow.cpp28
-rw-r--r--src/plugins/projectexplorer/projectwizardpage.cpp14
-rw-r--r--src/plugins/projectexplorer/rawprojectpart.cpp6
-rw-r--r--src/plugins/projectexplorer/rawprojectpart.h2
-rw-r--r--src/plugins/projectexplorer/runconfiguration.cpp34
-rw-r--r--src/plugins/projectexplorer/runconfiguration.h2
-rw-r--r--src/plugins/projectexplorer/runconfigurationaspects.cpp42
-rw-r--r--src/plugins/projectexplorer/runconfigurationaspects.h11
-rw-r--r--src/plugins/projectexplorer/runcontrol.cpp81
-rw-r--r--src/plugins/projectexplorer/runcontrol.h3
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.cpp12
-rw-r--r--src/plugins/projectexplorer/selectablefilesmodel.cpp14
-rw-r--r--src/plugins/projectexplorer/selectablefilesmodel.h7
-rw-r--r--src/plugins/projectexplorer/session.cpp1262
-rw-r--r--src/plugins/projectexplorer/session.h136
-rw-r--r--src/plugins/projectexplorer/sessiondialog.cpp223
-rw-r--r--src/plugins/projectexplorer/sessiondialog.h56
-rw-r--r--src/plugins/projectexplorer/sessionmodel.cpp266
-rw-r--r--src/plugins/projectexplorer/sessionmodel.h67
-rw-r--r--src/plugins/projectexplorer/sessionview.cpp152
-rw-r--r--src/plugins/projectexplorer/sessionview.h47
-rw-r--r--src/plugins/projectexplorer/target.cpp79
-rw-r--r--src/plugins/projectexplorer/target.h7
-rw-r--r--src/plugins/projectexplorer/targetsettingspanel.cpp14
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.cpp9
-rw-r--r--src/plugins/projectexplorer/targetsetupwidget.cpp6
-rw-r--r--src/plugins/projectexplorer/task.cpp48
-rw-r--r--src/plugins/projectexplorer/task.h6
-rw-r--r--src/plugins/projectexplorer/taskfile.cpp10
-rw-r--r--src/plugins/projectexplorer/taskhub.cpp10
-rw-r--r--src/plugins/projectexplorer/taskmodel.cpp85
-rw-r--r--src/plugins/projectexplorer/taskmodel.h2
-rw-r--r--src/plugins/projectexplorer/taskwindow.cpp660
-rw-r--r--src/plugins/projectexplorer/testdata/multi-target-project/CMakeLists.txt3
-rw-r--r--src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-app.pro4
-rw-r--r--src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-lib.cpp6
-rw-r--r--src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-lib.pro4
-rw-r--r--src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-main.cpp6
-rw-r--r--src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-shared.h3
-rw-r--r--src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project.pro4
-rw-r--r--src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project.qbs10
-rw-r--r--src/plugins/projectexplorer/toolchain.cpp23
-rw-r--r--src/plugins/projectexplorer/toolchain.h10
-rw-r--r--src/plugins/projectexplorer/toolchainconfigwidget.cpp2
-rw-r--r--src/plugins/projectexplorer/toolchainoptionspage.cpp45
-rw-r--r--src/plugins/projectexplorer/toolchainsettingsaccessor.cpp16
-rw-r--r--src/plugins/projectexplorer/treescanner.cpp16
-rw-r--r--src/plugins/projectexplorer/treescanner.h4
-rw-r--r--src/plugins/projectexplorer/userfileaccessor.cpp18
166 files changed, 3318 insertions, 4974 deletions
diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt
index d05509636e..d16e868a5c 100644
--- a/src/plugins/projectexplorer/CMakeLists.txt
+++ b/src/plugins/projectexplorer/CMakeLists.txt
@@ -28,6 +28,7 @@ add_qtc_plugin(ProjectExplorer
codestylesettingspropertiespage.cpp codestylesettingspropertiespage.h
compileoutputwindow.cpp compileoutputwindow.h
configtaskhandler.cpp configtaskhandler.h
+ copystep.cpp copystep.h
copytaskhandler.cpp copytaskhandler.h
currentprojectfilter.cpp currentprojectfilter.h
currentprojectfind.cpp currentprojectfind.h
@@ -65,8 +66,7 @@ add_qtc_plugin(ProjectExplorer
devicesupport/idevicefactory.cpp devicesupport/idevicefactory.h
devicesupport/idevicefwd.h
devicesupport/idevicewidget.h
- devicesupport/localprocesslist.cpp devicesupport/localprocesslist.h
- devicesupport/sshdeviceprocesslist.cpp devicesupport/sshdeviceprocesslist.h
+ devicesupport/processlist.cpp devicesupport/processlist.h
devicesupport/sshparameters.cpp devicesupport/sshparameters.h
devicesupport/sshsettings.cpp devicesupport/sshsettings.h
devicesupport/sshsettingspage.cpp devicesupport/sshsettingspage.h
@@ -115,7 +115,6 @@ add_qtc_plugin(ProjectExplorer
ldparser.cpp ldparser.h
lldparser.cpp lldparser.h
linuxiccparser.cpp linuxiccparser.h
- localenvironmentaspect.cpp localenvironmentaspect.h
makestep.cpp makestep.h
miniprojecttargetselector.cpp miniprojecttargetselector.h
msvcparser.cpp msvcparser.h
@@ -135,13 +134,12 @@ add_qtc_plugin(ProjectExplorer
projectexplorerconstants.cpp
projectexplorerconstants.h
projectexplorericons.cpp projectexplorericons.h
- projectexplorersettings.h
- projectexplorersettingspage.cpp projectexplorersettingspage.h
+ projectexplorersettings.cpp projectexplorersettings.h
projectexplorertr.h
projectfilewizardextension.cpp projectfilewizardextension.h
projectimporter.cpp projectimporter.h
projectmacro.cpp projectmacro.h
- projectmanager.h
+ projectmanager.cpp projectmanager.h
projectmodels.cpp projectmodels.h
projectnodes.cpp projectnodes.h
projectpanelfactory.cpp projectpanelfactory.h
@@ -159,10 +157,6 @@ add_qtc_plugin(ProjectExplorer
runsettingspropertiespage.cpp runsettingspropertiespage.h
sanitizerparser.cpp sanitizerparser.h
selectablefilesmodel.cpp selectablefilesmodel.h
- session.cpp session.h
- sessiondialog.cpp sessiondialog.h
- sessionmodel.cpp sessionmodel.h
- sessionview.cpp sessionview.h
showineditortaskhandler.cpp showineditortaskhandler.h
showoutputtaskhandler.cpp showoutputtaskhandler.h
simpleprojectwizard.cpp simpleprojectwizard.h
diff --git a/src/plugins/projectexplorer/ProjectExplorer.json.in b/src/plugins/projectexplorer/ProjectExplorer.json.in
index d96dcc26c6..c9b54ad441 100644
--- a/src/plugins/projectexplorer/ProjectExplorer.json.in
+++ b/src/plugins/projectexplorer/ProjectExplorer.json.in
@@ -24,14 +24,6 @@
\"Name\" : \"-ensure-kit-for-binary\",
\"Parameter\" : \"file path\",
\"Description\" : \"Create kit with architecture matching a given application or library\"
- },
- {
- \"Name\" : \"-lastsession\",
- \"Description\" : \"Restore the last session\"
- },
- {
- \"Name\" : \"<session>\",
- \"Description\" : \"Restore a saved session\"
}
],
$$dependencyList,
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index c838458aa5..806d9159f9 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -12,14 +12,15 @@
#include <utils/fileutils.h>
#include <utils/outputformatter.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <QTextDecoder>
#include <algorithm>
#include <memory>
+using namespace Tasking;
using namespace Utils;
namespace ProjectExplorer {
@@ -76,7 +77,7 @@ public:
void cleanUp(int exitCode, QProcess::ExitStatus status);
AbstractProcessStep *q;
- std::unique_ptr<QtcProcess> m_process;
+ std::unique_ptr<Process> m_process;
std::unique_ptr<TaskTree> m_taskTree;
ProcessParameters m_param;
ProcessParameters *m_displayedParams = &m_param;
@@ -182,9 +183,9 @@ void AbstractProcessStep::doRun()
setupStreams();
- d->m_process.reset(new QtcProcess);
+ d->m_process.reset(new Process);
setupProcess(d->m_process.get());
- connect(d->m_process.get(), &QtcProcess::done, this, &AbstractProcessStep::handleProcessDone);
+ connect(d->m_process.get(), &Process::done, this, &AbstractProcessStep::handleProcessDone);
d->m_process->start();
}
@@ -209,7 +210,7 @@ void AbstractProcessStep::setupStreams()
d->stderrStream = std::make_unique<QTextDecoder>(QTextCodec::codecForLocale());
}
-void AbstractProcessStep::setupProcess(QtcProcess *process)
+void AbstractProcessStep::setupProcess(Process *process)
{
process->setUseCtrlCStub(HostOsInfo::isWindowsHost());
process->setWorkingDirectory(d->m_param.effectiveWorkingDirectory());
@@ -224,15 +225,15 @@ void AbstractProcessStep::setupProcess(QtcProcess *process)
if (d->m_lowPriority && ProjectExplorerPlugin::projectExplorerSettings().lowBuildPriority)
process->setLowPriority();
- connect(process, &QtcProcess::readyReadStandardOutput, this, [this, process] {
+ connect(process, &Process::readyReadStandardOutput, this, [this, process] {
emit addOutput(d->stdoutStream->toUnicode(process->readAllRawStandardOutput()),
OutputFormat::Stdout, DontAppendNewline);
});
- connect(process, &QtcProcess::readyReadStandardError, this, [this, process] {
+ connect(process, &Process::readyReadStandardError, this, [this, process] {
emit addOutput(d->stderrStream->toUnicode(process->readAllRawStandardError()),
OutputFormat::Stderr, DontAppendNewline);
});
- connect(process, &QtcProcess::started, this, [this] {
+ connect(process, &Process::started, this, [this] {
ProcessParameters *params = displayedParameters();
emit addOutput(Tr::tr("Starting: \"%1\" %2")
.arg(params->effectiveCommand().toUserOutput(), params->prettyArguments()),
@@ -240,7 +241,7 @@ void AbstractProcessStep::setupProcess(QtcProcess *process)
});
}
-void AbstractProcessStep::runTaskTree(const Tasking::Group &recipe)
+void AbstractProcessStep::runTaskTree(const Group &recipe)
{
setupStreams();
@@ -306,7 +307,7 @@ bool AbstractProcessStep::setupProcessParameters(ProcessParameters *params) cons
const bool looksGood = executable.isEmpty() || executable.ensureReachable(workingDirectory);
QTC_ASSERT(looksGood, return false);
- params->setWorkingDirectory(workingDirectory.onDevice(executable));
+ params->setWorkingDirectory(executable.withNewPath(workingDirectory.path()));
return true;
}
diff --git a/src/plugins/projectexplorer/abstractprocessstep.h b/src/plugins/projectexplorer/abstractprocessstep.h
index 8112541447..fc1ed13135 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.h
+++ b/src/plugins/projectexplorer/abstractprocessstep.h
@@ -10,10 +10,11 @@
namespace Utils {
class CommandLine;
enum class ProcessResult;
-class QtcProcess;
-namespace Tasking { class Group; }
+class Process;
}
+namespace Tasking { class Group; }
+
namespace ProjectExplorer {
class ProcessParameters;
@@ -51,8 +52,8 @@ protected:
virtual void finish(Utils::ProcessResult result);
bool checkWorkingDirectory();
- void setupProcess(Utils::QtcProcess *process);
- void runTaskTree(const Utils::Tasking::Group &recipe);
+ void setupProcess(Utils::Process *process);
+ void runTaskTree(const Tasking::Group &recipe);
ProcessParameters *displayedParameters() const;
private:
diff --git a/src/plugins/projectexplorer/allprojectsfilter.cpp b/src/plugins/projectexplorer/allprojectsfilter.cpp
index ea4d86dba7..42e110d350 100644
--- a/src/plugins/projectexplorer/allprojectsfilter.cpp
+++ b/src/plugins/projectexplorer/allprojectsfilter.cpp
@@ -3,14 +3,17 @@
#include "allprojectsfilter.h"
+#include "project.h"
#include "projectexplorer.h"
#include "projectexplorertr.h"
-#include "session.h"
-#include "project.h"
+#include "projectmanager.h"
#include <utils/algorithm.h>
+#include <QFuture>
+
using namespace Core;
+using namespace Utils;
namespace ProjectExplorer::Internal {
@@ -18,38 +21,29 @@ AllProjectsFilter::AllProjectsFilter()
{
setId("Files in any project");
setDisplayName(Tr::tr("Files in Any Project"));
- setDescription(Tr::tr("Matches all files of all open projects. Append \"+<number>\" or "
- "\":<number>\" to jump to the given line number. Append another "
- "\"+<number>\" or \":<number>\" to jump to the column number as well."));
+ setDescription(Tr::tr("Locates files of all open projects. Append \"+<number>\" or "
+ "\":<number>\" to jump to the given line number. Append another "
+ "\"+<number>\" or \":<number>\" to jump to the column number as well."));
setDefaultShortcutString("a");
setDefaultIncludedByDefault(true);
+ setRefreshRecipe(Tasking::Sync([this] { m_cache.invalidate(); }));
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::fileListChanged,
- this, &AllProjectsFilter::markFilesAsOutOfDate);
-}
-
-void AllProjectsFilter::markFilesAsOutOfDate()
-{
- setFileIterator(nullptr);
-}
-
-void AllProjectsFilter::prepareSearch(const QString &entry)
-{
- Q_UNUSED(entry)
- if (!fileIterator()) {
- Utils::FilePaths paths;
- for (Project *project : SessionManager::projects())
- paths.append(project->files(Project::SourceFiles));
- Utils::sort(paths);
- setFileIterator(new BaseFileFilter::ListIterator(paths));
- }
- BaseFileFilter::prepareSearch(entry);
-}
-
-void AllProjectsFilter::refresh(QFutureInterface<void> &future)
-{
- Q_UNUSED(future)
- QMetaObject::invokeMethod(this, &AllProjectsFilter::markFilesAsOutOfDate, Qt::QueuedConnection);
+ this, [this] { m_cache.invalidate(); });
+ m_cache.setGeneratorProvider([] {
+ // This body runs in main thread
+ FilePaths filePaths;
+ for (Project *project : ProjectManager::projects())
+ filePaths.append(project->files(Project::SourceFiles));
+ return [filePaths](const QFuture<void> &future) {
+ // This body runs in non-main thread
+ FilePaths sortedPaths = filePaths;
+ if (future.isCanceled())
+ return FilePaths();
+ Utils::sort(sortedPaths);
+ return sortedPaths;
+ };
+ });
}
-} // ProjectExplorer::Internal
+} // namespace ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/allprojectsfilter.h b/src/plugins/projectexplorer/allprojectsfilter.h
index ae9fdffe92..6782ef4611 100644
--- a/src/plugins/projectexplorer/allprojectsfilter.h
+++ b/src/plugins/projectexplorer/allprojectsfilter.h
@@ -3,25 +3,18 @@
#pragma once
-#include <coreplugin/locator/basefilefilter.h>
+#include <coreplugin/locator/ilocatorfilter.h>
-#include <QFutureInterface>
+namespace ProjectExplorer::Internal {
-namespace ProjectExplorer {
-namespace Internal {
-
-class AllProjectsFilter : public Core::BaseFileFilter
+class AllProjectsFilter : public Core::ILocatorFilter
{
- Q_OBJECT
-
public:
AllProjectsFilter();
- void refresh(QFutureInterface<void> &future) override;
- void prepareSearch(const QString &entry) override;
private:
- void markFilesAsOutOfDate();
+ Core::LocatorMatcherTasks matchers() final { return {m_cache.matcher()}; }
+ Core::LocatorFileCache m_cache;
};
-} // namespace Internal
-} // namespace ProjectExplorer
+} // namespace ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp
index ac4afc1d6e..d61b156052 100644
--- a/src/plugins/projectexplorer/allprojectsfind.cpp
+++ b/src/plugins/projectexplorer/allprojectsfind.cpp
@@ -7,7 +7,7 @@
#include "project.h"
#include "projectexplorer.h"
#include "projectexplorertr.h"
-#include "session.h"
+#include "projectmanager.h"
#include <coreplugin/editormanager/editormanager.h>
@@ -44,7 +44,7 @@ QString AllProjectsFind::displayName() const
bool AllProjectsFind::isEnabled() const
{
- return BaseFileFind::isEnabled() && SessionManager::hasProjects();
+ return BaseFileFind::isEnabled() && ProjectManager::hasProjects();
}
FileIterator *AllProjectsFind::files(const QStringList &nameFilters,
@@ -52,7 +52,7 @@ FileIterator *AllProjectsFind::files(const QStringList &nameFilters,
const QVariant &additionalParameters) const
{
Q_UNUSED(additionalParameters)
- return filesForProjects(nameFilters, exclusionFilters, SessionManager::projects());
+ return filesForProjects(nameFilters, exclusionFilters, ProjectManager::projects());
}
FileIterator *AllProjectsFind::filesForProjects(const QStringList &nameFilters,
diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp
index 6f7e22bacd..3c76c2e62a 100644
--- a/src/plugins/projectexplorer/appoutputpane.cpp
+++ b/src/plugins/projectexplorer/appoutputpane.cpp
@@ -8,7 +8,6 @@
#include "projectexplorericons.h"
#include "projectexplorertr.h"
#include "runcontrol.h"
-#include "session.h"
#include "showoutputtaskhandler.h"
#include "windebuginterface.h"
@@ -17,6 +16,7 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/outputwindow.h>
+#include <coreplugin/session.h>
#include <texteditor/behaviorsettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorsettings.h>
@@ -46,6 +46,7 @@
static Q_LOGGING_CATEGORY(appOutputLog, "qtc.projectexplorer.appoutput", QtWarningMsg);
+using namespace Core;
using namespace Utils;
namespace ProjectExplorer {
diff --git a/src/plugins/projectexplorer/buildaspects.cpp b/src/plugins/projectexplorer/buildaspects.cpp
index adf37a3362..606911654f 100644
--- a/src/plugins/projectexplorer/buildaspects.cpp
+++ b/src/plugins/projectexplorer/buildaspects.cpp
@@ -41,7 +41,6 @@ BuildDirectoryAspect::BuildDirectoryAspect(const BuildConfiguration *bc)
{
setSettingsKey("ProjectExplorer.BuildConfiguration.BuildDirectory");
setLabelText(Tr::tr("Build directory:"));
- setDisplayStyle(PathChooserDisplay);
setExpectedKind(Utils::PathChooser::Directory);
setValidationFunction([this](FancyLineEdit *edit, QString *error) {
const FilePath fixedDir = fixupDir(FilePath::fromUserInput(edit->text()));
@@ -107,12 +106,12 @@ void BuildDirectoryAspect::fromMap(const QVariantMap &map)
}
}
-void BuildDirectoryAspect::addToLayout(Layouting::LayoutBuilder &builder)
+void BuildDirectoryAspect::addToLayout(Layouting::LayoutItem &parent)
{
- StringAspect::addToLayout(builder);
+ StringAspect::addToLayout(parent);
d->problemLabel = new InfoLabel({}, InfoLabel::Warning);
d->problemLabel->setElideMode(Qt::ElideNone);
- builder.addRow({{}, d->problemLabel.data()});
+ parent.addItems({{}, d->problemLabel.data()});
updateProblemLabel();
if (!d->sourceDir.isEmpty()) {
connect(this, &StringAspect::checkedChanged, this, [this] {
diff --git a/src/plugins/projectexplorer/buildaspects.h b/src/plugins/projectexplorer/buildaspects.h
index 9788cc69ca..bcc8987cd0 100644
--- a/src/plugins/projectexplorer/buildaspects.h
+++ b/src/plugins/projectexplorer/buildaspects.h
@@ -7,12 +7,11 @@
#include <utils/aspects.h>
-namespace Utils { class FilePath; }
-
namespace ProjectExplorer {
+
class BuildConfiguration;
-class PROJECTEXPLORER_EXPORT BuildDirectoryAspect : public Utils::StringAspect
+class PROJECTEXPLORER_EXPORT BuildDirectoryAspect : public Utils::FilePathAspect
{
Q_OBJECT
public:
@@ -23,7 +22,7 @@ public:
bool isShadowBuild() const;
void setProblem(const QString &description);
- void addToLayout(Utils::Layouting::LayoutBuilder &builder) override;
+ void addToLayout(Layouting::LayoutItem &parent) override;
static Utils::FilePath fixupDir(const Utils::FilePath &dir);
diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp
index ff14b7ab07..70d5a348c1 100644
--- a/src/plugins/projectexplorer/buildconfiguration.cpp
+++ b/src/plugins/projectexplorer/buildconfiguration.cpp
@@ -17,8 +17,8 @@
#include "projectexplorer.h"
#include "projectexplorertr.h"
#include "project.h"
+#include "projectmanager.h"
#include "projecttree.h"
-#include "session.h"
#include "target.h"
#include <coreplugin/fileutils.h>
@@ -167,6 +167,10 @@ BuildConfiguration::BuildConfiguration(Target *target, Utils::Id id)
expander->registerVariable("buildDir", Tr::tr("Build directory"),
[this] { return buildDirectory().toUserOutput(); });
+ expander->registerFileVariables("BuildConfig:BuildDirectory",
+ Tr::tr("Build directory"),
+ [this] { return buildDirectory(); });
+
expander->registerVariable("BuildConfig:Name", Tr::tr("Name of the build configuration"),
[this] { return displayName(); });
@@ -209,7 +213,7 @@ BuildConfiguration::BuildConfiguration(Target *target, Utils::Id id)
connect(target, &Target::parsingStarted, this, &BuildConfiguration::enabledChanged);
connect(target, &Target::parsingFinished, this, &BuildConfiguration::enabledChanged);
connect(this, &BuildConfiguration::enabledChanged, this, [this] {
- if (isActive() && project() == SessionManager::startupProject()) {
+ if (isActive() && project() == ProjectManager::startupProject()) {
ProjectExplorerPlugin::updateActions();
ProjectExplorerPlugin::updateRunActions();
}
@@ -318,12 +322,15 @@ NamedWidget *BuildConfiguration::createConfigWidget()
widget = named;
}
- Layouting::Form builder;
+ Layouting::Form form;
for (BaseAspect *aspect : aspects()) {
- if (aspect->isVisible())
- aspect->addToLayout(builder.finishRow());
+ if (aspect->isVisible()) {
+ form.addItem(aspect);
+ form.addItem(Layouting::br);
+ }
}
- builder.attachTo(widget, Layouting::WithoutMargins);
+ form.addItem(Layouting::noMargin);
+ form.attachTo(widget);
return named;
}
@@ -612,13 +619,27 @@ FilePath BuildConfiguration::buildDirectoryFromTemplate(const FilePath &projectD
[buildType] { return buildTypeName(buildType); });
exp.registerSubProvider([kit] { return kit->macroExpander(); });
- QString buildDir = ProjectExplorerPlugin::buildDirectoryTemplate();
- qCDebug(bcLog) << "build dir template:" << buildDir;
+ FilePath buildDir = FilePath::fromUserInput(ProjectExplorerPlugin::buildDirectoryTemplate());
+ qCDebug(bcLog) << "build dir template:" << buildDir.toUserOutput();
buildDir = exp.expand(buildDir);
- qCDebug(bcLog) << "expanded build:" << buildDir;
- buildDir.replace(" ", "-");
+ qCDebug(bcLog) << "expanded build:" << buildDir.toUserOutput();
+ buildDir = buildDir.withNewPath(buildDir.path().replace(" ", "-"));
+
+ auto buildDevice = BuildDeviceKitAspect::device(kit);
+
+ if (buildDir.isAbsolutePath()) {
+ bool isReachable = buildDevice->ensureReachable(buildDir);
+ if (!isReachable)
+ return {};
+ return buildDevice->rootPath().withNewMappedPath(buildDir);
+ }
+
+ bool isReachable = buildDevice->ensureReachable(projectDir);
+ if (!isReachable)
+ return {};
- return projectDir.resolvePath(buildDir);
+ const FilePath baseDir = buildDevice->rootPath().withNewMappedPath(projectDir);
+ return baseDir.resolvePath(buildDir);
}
///
// IBuildConfigurationFactory
diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp
index 57bfde6e46..28169513cb 100644
--- a/src/plugins/projectexplorer/buildmanager.cpp
+++ b/src/plugins/projectexplorer/buildmanager.cpp
@@ -16,8 +16,8 @@
#include "projectexplorerconstants.h"
#include "projectexplorersettings.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "runcontrol.h"
-#include "session.h"
#include "target.h"
#include "task.h"
#include "taskhub.h"
@@ -258,7 +258,7 @@ BuildManager::BuildManager(QObject *parent, QAction *cancelBuildAction)
m_instance = this;
d = new BuildManagerPrivate;
- connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject,
+ connect(ProjectManager::instance(), &ProjectManager::aboutToRemoveProject,
this, &BuildManager::aboutToRemoveProject);
d->m_outputWindow = new Internal::CompileOutputWindow(cancelBuildAction);
@@ -318,19 +318,19 @@ void BuildManager::rebuildProjectWithoutDependencies(Project *project)
void BuildManager::buildProjectWithDependencies(Project *project, ConfigSelection configSelection)
{
- queue(SessionManager::projectOrder(project), {Id(Constants::BUILDSTEPS_BUILD)},
+ queue(ProjectManager::projectOrder(project), {Id(Constants::BUILDSTEPS_BUILD)},
configSelection);
}
void BuildManager::cleanProjectWithDependencies(Project *project, ConfigSelection configSelection)
{
- queue(SessionManager::projectOrder(project), {Id(Constants::BUILDSTEPS_CLEAN)},
+ queue(ProjectManager::projectOrder(project), {Id(Constants::BUILDSTEPS_CLEAN)},
configSelection);
}
void BuildManager::rebuildProjectWithDependencies(Project *project, ConfigSelection configSelection)
{
- queue(SessionManager::projectOrder(project),
+ queue(ProjectManager::projectOrder(project),
{Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD)},
configSelection);
}
@@ -384,7 +384,7 @@ BuildForRunConfigStatus BuildManager::potentiallyBuildForRunConfig(RunConfigurat
}
Project * const pro = rc->target()->project();
- const int queueCount = queue(SessionManager::projectOrder(pro), stepIds,
+ const int queueCount = queue(ProjectManager::projectOrder(pro), stepIds,
ConfigSelection::Active, rc);
if (rc->target()->activeBuildConfiguration())
rc->target()->activeBuildConfiguration()->restrictNextBuild(nullptr);
@@ -442,16 +442,6 @@ int BuildManager::getErrorTaskCount()
return errors;
}
-void BuildManager::setCompileOutputSettings(const CompileOutputSettings &settings)
-{
- d->m_outputWindow->setSettings(settings);
-}
-
-const CompileOutputSettings &BuildManager::compileOutputSettings()
-{
- return d->m_outputWindow->settings();
-}
-
QString BuildManager::displayNameForStepId(Id stepId)
{
if (stepId == Constants::BUILDSTEPS_CLEAN) {
@@ -853,7 +843,7 @@ bool BuildManager::buildLists(const QList<BuildStepList *> bsls, const QStringLi
return false;
}
- if (d->m_outputWindow->settings().popUp)
+ if (CompileOutputSettings::instance().popUp())
d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
startBuildQueue();
return true;
@@ -866,7 +856,7 @@ void BuildManager::appendStep(BuildStep *step, const QString &name)
d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
return;
}
- if (d->m_outputWindow->settings().popUp)
+ if (CompileOutputSettings::instance().popUp())
d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
startBuildQueue();
}
diff --git a/src/plugins/projectexplorer/buildmanager.h b/src/plugins/projectexplorer/buildmanager.h
index d7d2c91562..d9478db409 100644
--- a/src/plugins/projectexplorer/buildmanager.h
+++ b/src/plugins/projectexplorer/buildmanager.h
@@ -10,12 +10,10 @@
#include <QStringList>
namespace ProjectExplorer {
-class RunConfiguration;
-
-namespace Internal { class CompileOutputSettings; }
-class Task;
class Project;
+class RunConfiguration;
+class Task;
enum class BuildForRunConfigStatus { Building, NotBuilding, BuildFailed };
enum class ConfigSelection { All, Active };
@@ -66,9 +64,6 @@ public:
static int getErrorTaskCount();
- static void setCompileOutputSettings(const Internal::CompileOutputSettings &settings);
- static const Internal::CompileOutputSettings &compileOutputSettings();
-
static QString displayNameForStepId(Utils::Id stepId);
public slots:
diff --git a/src/plugins/projectexplorer/buildpropertiessettings.cpp b/src/plugins/projectexplorer/buildpropertiessettings.cpp
index a9126551e3..6df8fdd328 100644
--- a/src/plugins/projectexplorer/buildpropertiessettings.cpp
+++ b/src/plugins/projectexplorer/buildpropertiessettings.cpp
@@ -16,15 +16,33 @@ namespace ProjectExplorer {
const char DEFAULT_BUILD_DIRECTORY_TEMPLATE[]
= "../%{JS: Util.asciify(\"build-%{Project:Name}-%{Kit:FileSystemName}-%{BuildConfig:Name}\")}";
-BuildPropertiesSettings::BuildTriStateAspect::BuildTriStateAspect()
- : TriStateAspect{Tr::tr("Enable"), Tr::tr("Disable"), Tr::tr("Use Project Default")}
+BuildPropertiesSettings::BuildTriStateAspect::BuildTriStateAspect(AspectContainer *container)
+ : TriStateAspect(container, Tr::tr("Enable"), Tr::tr("Disable"), Tr::tr("Use Project Default"))
{}
BuildPropertiesSettings::BuildPropertiesSettings()
{
setAutoApply(false);
- registerAspect(&buildDirectoryTemplate);
+ setId("AB.ProjectExplorer.BuildPropertiesSettingsPage");
+ setDisplayName(Tr::tr("Default Build Properties"));
+ setCategory(ProjectExplorer::Constants::BUILD_AND_RUN_SETTINGS_CATEGORY);
+ setSettings(this);
+
+ setLayouter([this] {
+ using namespace Layouting;
+
+ return Column {
+ Form {
+ buildDirectoryTemplate, br,
+ separateDebugInfo, br,
+ qmlDebugging, br,
+ qtQuickCompiler
+ },
+ st
+ };
+ });
+
buildDirectoryTemplate.setDisplayStyle(StringAspect::LineEditDisplay);
buildDirectoryTemplate.setSettingsKey("Directories/BuildDirectory.TemplateV2");
buildDirectoryTemplate.setDefaultValue(DEFAULT_BUILD_DIRECTORY_TEMPLATE);
@@ -32,19 +50,12 @@ BuildPropertiesSettings::BuildPropertiesSettings()
buildDirectoryTemplate.setUseGlobalMacroExpander();
buildDirectoryTemplate.setUseResetButton();
- registerAspect(&buildDirectoryTemplateOld); // TODO: Remove in ~4.16
- buildDirectoryTemplateOld.setSettingsKey("Directories/BuildDirectory.Template");
- buildDirectoryTemplateOld.setDefaultValue(DEFAULT_BUILD_DIRECTORY_TEMPLATE);
-
- registerAspect(&separateDebugInfo);
separateDebugInfo.setSettingsKey("ProjectExplorer/Settings/SeparateDebugInfo");
separateDebugInfo.setLabelText(Tr::tr("Separate debug info:"));
- registerAspect(&qmlDebugging);
qmlDebugging.setSettingsKey("ProjectExplorer/Settings/QmlDebugging");
qmlDebugging.setLabelText(Tr::tr("QML debugging:"));
- registerAspect(&qtQuickCompiler);
qtQuickCompiler.setSettingsKey("ProjectExplorer/Settings/QtQuickCompiler");
qtQuickCompiler.setLabelText(Tr::tr("Use qmlcachegen:"));
@@ -54,51 +65,9 @@ BuildPropertiesSettings::BuildPropertiesSettings()
&qtQuickCompiler, &BaseAspect::setVisible);
}
-void BuildPropertiesSettings::readSettings(QSettings *s)
-{
- AspectContainer::readSettings(s);
-
- // TODO: Remove in ~4.16
- QString v = buildDirectoryTemplate.value();
- if (v.isEmpty())
- v = buildDirectoryTemplateOld.value();
- if (v.isEmpty())
- v = DEFAULT_BUILD_DIRECTORY_TEMPLATE;
- v.replace("%{CurrentProject:Name}", "%{Project:Name}");
- v.replace("%{CurrentKit:FileSystemName}", "%{Kit:FileSystemName}");
- v.replace("%{CurrentBuild:Name}", "%{BuildConfig:Name}");
- buildDirectoryTemplate.setValue(v);
-}
-
QString BuildPropertiesSettings::defaultBuildDirectoryTemplate()
{
return QString(DEFAULT_BUILD_DIRECTORY_TEMPLATE);
}
-namespace Internal {
-
-BuildPropertiesSettingsPage::BuildPropertiesSettingsPage(BuildPropertiesSettings *settings)
-{
- setId("AB.ProjectExplorer.BuildPropertiesSettingsPage");
- setDisplayName(Tr::tr("Default Build Properties"));
- setCategory(ProjectExplorer::Constants::BUILD_AND_RUN_SETTINGS_CATEGORY);
- setSettings(settings);
-
- setLayouter([settings](QWidget *widget) {
- BuildPropertiesSettings &s = *settings;
- using namespace Layouting;
-
- Column {
- Form {
- s.buildDirectoryTemplate,
- s.separateDebugInfo,
- s.qmlDebugging,
- s.qtQuickCompiler
- },
- st
- }.attachTo(widget);
- });
-}
-
-} // Internal
} // ProjectExplorer
diff --git a/src/plugins/projectexplorer/buildpropertiessettings.h b/src/plugins/projectexplorer/buildpropertiessettings.h
index 75ec957a4e..3b1b2b7c69 100644
--- a/src/plugins/projectexplorer/buildpropertiessettings.h
+++ b/src/plugins/projectexplorer/buildpropertiessettings.h
@@ -7,11 +7,9 @@
#include <coreplugin/dialogs/ioptionspage.h>
-#include <utils/aspects.h>
-
namespace ProjectExplorer {
-class PROJECTEXPLORER_EXPORT BuildPropertiesSettings : public Utils::AspectContainer
+class PROJECTEXPLORER_EXPORT BuildPropertiesSettings : public Core::PagedSettings
{
public:
BuildPropertiesSettings();
@@ -19,28 +17,16 @@ public:
class BuildTriStateAspect : public Utils::TriStateAspect
{
public:
- BuildTriStateAspect();
+ explicit BuildTriStateAspect(AspectContainer *container);
};
- Utils::StringAspect buildDirectoryTemplate;
- Utils::StringAspect buildDirectoryTemplateOld; // TODO: Remove in ~4.16
- BuildTriStateAspect separateDebugInfo;
- BuildTriStateAspect qmlDebugging;
- BuildTriStateAspect qtQuickCompiler;
+ Utils::StringAspect buildDirectoryTemplate{this};
+ BuildTriStateAspect separateDebugInfo{this};
+ BuildTriStateAspect qmlDebugging{this};
+ BuildTriStateAspect qtQuickCompiler{this};
Utils::BoolAspect showQtSettings;
- void readSettings(QSettings *settings);
-
QString defaultBuildDirectoryTemplate();
};
-namespace Internal {
-
-class BuildPropertiesSettingsPage final : public Core::IOptionsPage
-{
-public:
- explicit BuildPropertiesSettingsPage(BuildPropertiesSettings *settings);
-};
-
-} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
index 410449083c..2caa44712e 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
@@ -10,10 +10,10 @@
#include "project.h"
#include "projectconfigurationmodel.h"
#include "projectexplorertr.h"
-#include "session.h"
#include "target.h"
#include <coreplugin/icore.h>
+#include <coreplugin/session.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -185,7 +185,7 @@ void BuildSettingsWidget::currentIndexChanged(int index)
{
auto buildConfiguration = qobject_cast<BuildConfiguration *>(
m_target->buildConfigurationModel()->projectConfigurationAt(index));
- SessionManager::setActiveBuildConfiguration(m_target, buildConfiguration, SetActive::Cascade);
+ m_target->setActiveBuildConfiguration(buildConfiguration, SetActive::Cascade);
}
void BuildSettingsWidget::updateActiveConfiguration()
@@ -222,7 +222,7 @@ void BuildSettingsWidget::createConfiguration(const BuildInfo &info_)
return;
m_target->addBuildConfiguration(bc);
- SessionManager::setActiveBuildConfiguration(m_target, bc, SetActive::Cascade);
+ m_target->setActiveBuildConfiguration(bc, SetActive::Cascade);
}
QString BuildSettingsWidget::uniqueName(const QString & name)
@@ -286,7 +286,7 @@ void BuildSettingsWidget::cloneConfiguration()
bc->setDisplayName(name);
const FilePath buildDirectory = bc->buildDirectory();
if (buildDirectory != m_target->project()->projectDirectory()) {
- const std::function<bool(const FilePath &)> isBuildDirOk = [this](const FilePath &candidate) {
+ const FilePathPredicate isBuildDirOk = [this](const FilePath &candidate) {
if (candidate.exists())
return false;
return !anyOf(m_target->buildConfigurations(), [&candidate](const BuildConfiguration *bc) {
@@ -295,7 +295,7 @@ void BuildSettingsWidget::cloneConfiguration()
bc->setBuildDirectory(makeUniquelyNumbered(buildDirectory, isBuildDirOk));
}
m_target->addBuildConfiguration(bc);
- SessionManager::setActiveBuildConfiguration(m_target, bc, SetActive::Cascade);
+ m_target->setActiveBuildConfiguration(bc, SetActive::Cascade);
}
void BuildSettingsWidget::deleteConfiguration(BuildConfiguration *deleteConfiguration)
diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp
index c078a73d82..32be37048e 100644
--- a/src/plugins/projectexplorer/buildstep.cpp
+++ b/src/plugins/projectexplorer/buildstep.cpp
@@ -147,7 +147,7 @@ QWidget *BuildStep::doCreateConfigWidget()
setSummaryText(m_summaryUpdater());
};
- for (BaseAspect *aspect : std::as_const(m_aspects))
+ for (BaseAspect *aspect : std::as_const(*this))
connect(aspect, &BaseAspect::changed, widget, recreateSummary);
connect(buildConfiguration(), &BuildConfiguration::buildDirectoryChanged,
@@ -160,12 +160,13 @@ QWidget *BuildStep::doCreateConfigWidget()
QWidget *BuildStep::createConfigWidget()
{
- Layouting::Form builder;
- for (BaseAspect *aspect : std::as_const(m_aspects)) {
+ Layouting::Form form;
+ for (BaseAspect *aspect : std::as_const(*this)) {
if (aspect->isVisible())
- aspect->addToLayout(builder.finishRow());
+ form.addItem(aspect);
}
- auto widget = builder.emerge(Layouting::WithoutMargins);
+ form.addItem(Layouting::noMargin);
+ auto widget = form.emerge();
if (m_addMacroExpander)
VariableChooser::addSupportForChildWidgets(widget, macroExpander());
@@ -361,7 +362,7 @@ bool BuildStepFactory::canHandle(BuildStepList *bsl) const
return false;
}
- if (!m_isRepeatable && bsl->contains(m_info.id))
+ if (!m_isRepeatable && bsl->contains(m_stepId))
return false;
if (m_supportedConfiguration.isValid()) {
@@ -375,14 +376,42 @@ bool BuildStepFactory::canHandle(BuildStepList *bsl) const
return true;
}
+QString BuildStepFactory::displayName() const
+{
+ return m_displayName;
+}
+
+void BuildStepFactory::cloneStepCreator(Id exitstingStepId, Id overrideNewStepId)
+{
+ m_stepId = {};
+ m_creator = {};
+ for (BuildStepFactory *factory : BuildStepFactory::allBuildStepFactories()) {
+ if (factory->m_stepId == exitstingStepId) {
+ m_creator = factory->m_creator;
+ m_stepId = factory->m_stepId;
+ m_displayName = factory->m_displayName;
+ // Other bits are intentionally not copied as they are unlikely to be
+ // useful in the cloner's context. The cloner can/has to finish the
+ // setup on its own.
+ break;
+ }
+ }
+ // Existence should be guaranteed by plugin dependencies. In case it fails,
+ // bark and keep the factory in a state where the invalid m_stepId keeps it
+ // inaction.
+ QTC_ASSERT(m_creator, return);
+ if (overrideNewStepId.isValid())
+ m_stepId = overrideNewStepId;
+}
+
void BuildStepFactory::setDisplayName(const QString &displayName)
{
- m_info.displayName = displayName;
+ m_displayName = displayName;
}
-void BuildStepFactory::setFlags(BuildStepInfo::Flags flags)
+void BuildStepFactory::setFlags(BuildStep::Flags flags)
{
- m_info.flags = flags;
+ m_flags = flags;
}
void BuildStepFactory::setSupportedStepList(Id id)
@@ -415,20 +444,21 @@ void BuildStepFactory::setSupportedDeviceTypes(const QList<Id> &ids)
m_supportedDeviceTypes = ids;
}
-BuildStepInfo BuildStepFactory::stepInfo() const
+BuildStep::Flags BuildStepFactory::stepFlags() const
{
- return m_info;
+ return m_flags;
}
Id BuildStepFactory::stepId() const
{
- return m_info.id;
+ return m_stepId;
}
BuildStep *BuildStepFactory::create(BuildStepList *parent)
{
- BuildStep *step = m_info.creator(parent);
- step->setDefaultDisplayName(m_info.displayName);
+ QTC_ASSERT(m_creator, return nullptr);
+ BuildStep *step = m_creator(parent);
+ step->setDefaultDisplayName(m_displayName);
return step;
}
diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h
index 547a5e2027..46be75f563 100644
--- a/src/plugins/projectexplorer/buildstep.h
+++ b/src/plugins/projectexplorer/buildstep.h
@@ -76,6 +76,12 @@ public:
enum OutputNewlineSetting { DoAppendNewline, DontAppendNewline };
+ enum Flags {
+ Uncreatable = 1 << 0,
+ Unclonable = 1 << 1,
+ UniqueStep = 1 << 8 // Can't be used twice in a BuildStepList
+ };
+
bool widgetExpandedByDefault() const;
void setWidgetExpandedByDefault(bool widgetExpandedByDefault);
@@ -136,23 +142,6 @@ private:
QString m_summaryText;
};
-class PROJECTEXPLORER_EXPORT BuildStepInfo
-{
-public:
- enum Flags {
- Uncreatable = 1 << 0,
- Unclonable = 1 << 1,
- UniqueStep = 1 << 8 // Can't be used twice in a BuildStepList
- };
-
- using BuildStepCreator = std::function<BuildStep *(BuildStepList *)>;
-
- Utils::Id id;
- QString displayName;
- Flags flags = Flags();
- BuildStepCreator creator;
-};
-
class PROJECTEXPLORER_EXPORT BuildStepFactory
{
public:
@@ -163,23 +152,26 @@ public:
static const QList<BuildStepFactory *> allBuildStepFactories();
- BuildStepInfo stepInfo() const;
+ BuildStep::Flags stepFlags() const;
Utils::Id stepId() const;
BuildStep *create(BuildStepList *parent);
BuildStep *restore(BuildStepList *parent, const QVariantMap &map);
bool canHandle(BuildStepList *bsl) const;
+ QString displayName() const;
+
protected:
using BuildStepCreator = std::function<BuildStep *(BuildStepList *)>;
template <class BuildStepType>
void registerStep(Utils::Id id)
{
- QTC_CHECK(!m_info.creator);
- m_info.id = id;
- m_info.creator = [id](BuildStepList *bsl) { return new BuildStepType(bsl, id); };
+ QTC_CHECK(!m_creator);
+ m_stepId = id;
+ m_creator = [id](BuildStepList *bsl) { return new BuildStepType(bsl, id); };
}
+ void cloneStepCreator(Utils::Id exitstingStepId, Utils::Id overrideNewStepId = {});
void setSupportedStepList(Utils::Id id);
void setSupportedStepLists(const QList<Utils::Id> &ids);
@@ -189,10 +181,13 @@ protected:
void setSupportedDeviceTypes(const QList<Utils::Id> &ids);
void setRepeatable(bool on) { m_isRepeatable = on; }
void setDisplayName(const QString &displayName);
- void setFlags(BuildStepInfo::Flags flags);
+ void setFlags(BuildStep::Flags flags);
private:
- BuildStepInfo m_info;
+ Utils::Id m_stepId;
+ QString m_displayName;
+ BuildStep::Flags m_flags = {};
+ BuildStepCreator m_creator;
Utils::Id m_supportedProjectType;
QList<Utils::Id> m_supportedDeviceTypes;
diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp
index 8d6159541e..0094bf0b68 100644
--- a/src/plugins/projectexplorer/buildsteplist.cpp
+++ b/src/plugins/projectexplorer/buildsteplist.cpp
@@ -43,16 +43,6 @@ QVariantMap BuildStepList::toMap() const
{
QVariantMap map;
- {
- // Only written for compatibility reasons within the 4.11 cycle
- const char CONFIGURATION_ID_KEY[] = "ProjectExplorer.ProjectConfiguration.Id";
- const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DisplayName";
- const char DEFAULT_DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DefaultDisplayName";
- map.insert(QLatin1String(CONFIGURATION_ID_KEY), m_id.toSetting());
- map.insert(QLatin1String(DISPLAY_NAME_KEY), displayName());
- map.insert(QLatin1String(DEFAULT_DISPLAY_NAME_KEY), displayName());
- }
-
// Save build steps
map.insert(QString::fromLatin1(STEPS_COUNT_KEY), m_steps.count());
for (int i = 0; i < m_steps.count(); ++i)
diff --git a/src/plugins/projectexplorer/buildstepspage.cpp b/src/plugins/projectexplorer/buildstepspage.cpp
index 241d2a9835..21fb4c2093 100644
--- a/src/plugins/projectexplorer/buildstepspage.cpp
+++ b/src/plugins/projectexplorer/buildstepspage.cpp
@@ -209,14 +209,14 @@ void BuildStepListWidget::updateAddBuildStepMenu()
if (!factory->canHandle(m_buildStepList))
continue;
- const BuildStepInfo &info = factory->stepInfo();
- if (info.flags & BuildStepInfo::Uncreatable)
+ const BuildStep::Flags flags = factory->stepFlags();
+ if (flags & BuildStep::Uncreatable)
continue;
- if ((info.flags & BuildStepInfo::UniqueStep) && m_buildStepList->contains(info.id))
+ if ((flags & BuildStep::UniqueStep) && m_buildStepList->contains(factory->stepId()))
continue;
- QAction *action = menu->addAction(info.displayName);
+ QAction *action = menu->addAction(factory->displayName());
connect(action, &QAction::triggered, this, [factory, this] {
BuildStep *newStep = factory->create(m_buildStepList);
QTC_ASSERT(newStep, return);
diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp
index 0a2c2f3a85..9a120a9863 100644
--- a/src/plugins/projectexplorer/buildsystem.cpp
+++ b/src/plugins/projectexplorer/buildsystem.cpp
@@ -7,9 +7,9 @@
#include "extracompiler.h"
#include "projectexplorer.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "runconfiguration.h"
#include "runcontrol.h"
-#include "session.h"
#include "target.h"
#include <coreplugin/messagemanager.h>
@@ -64,7 +64,7 @@ BuildSystem::BuildSystem(Target *target)
connect(&d->m_delayedParsingTimer, &QTimer::timeout, this,
[this] {
- if (SessionManager::hasProject(project()))
+ if (ProjectManager::hasProject(project()))
triggerParsing();
else
requestDelayedParse();
@@ -325,7 +325,6 @@ void BuildSystem::setDeploymentData(const DeploymentData &deploymentData)
if (d->m_deploymentData != deploymentData) {
d->m_deploymentData = deploymentData;
emit deploymentDataChanged();
- emit applicationTargetsChanged();
emit target()->deploymentDataChanged();
}
}
@@ -337,10 +336,7 @@ DeploymentData BuildSystem::deploymentData() const
void BuildSystem::setApplicationTargets(const QList<BuildTargetInfo> &appTargets)
{
- if (Utils::toSet(appTargets) != Utils::toSet(d->m_appTargets)) {
- d->m_appTargets = appTargets;
- emit applicationTargetsChanged();
- }
+ d->m_appTargets = appTargets;
}
const QList<BuildTargetInfo> BuildSystem::applicationTargets() const
diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h
index 0d19c9110e..1cd1e41a06 100644
--- a/src/plugins/projectexplorer/buildsystem.h
+++ b/src/plugins/projectexplorer/buildsystem.h
@@ -152,7 +152,6 @@ signals:
void parsingStarted();
void parsingFinished(bool success);
void deploymentDataChanged();
- void applicationTargetsChanged();
void testInformationUpdated();
protected:
diff --git a/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp b/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
index 2ff0285a61..f7ed131e57 100644
--- a/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/codestylesettingspropertiespage.cpp
@@ -48,12 +48,13 @@ CodeStyleSettingsWidget::CodeStyleSettingsWidget(Project *project)
connect(languageComboBox, &QComboBox::currentIndexChanged,
stackedWidget, &QStackedWidget::setCurrentIndex);
- using namespace Utils::Layouting;
+ using namespace Layouting;
Column {
Row { new QLabel(Tr::tr("Language:")), languageComboBox, st },
- stackedWidget
- }.attachTo(this, WithoutMargins);
+ stackedWidget,
+ noMargin
+ }.attachTo(this);
}
} // ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp
index f345792ca8..bafc31fc14 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.cpp
+++ b/src/plugins/projectexplorer/compileoutputwindow.cpp
@@ -17,7 +17,9 @@
#include <texteditor/texteditorsettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/behaviorsettings.h>
+
#include <utils/algorithm.h>
+#include <utils/layoutbuilder.h>
#include <utils/outputformatter.h>
#include <utils/proxyaction.h>
#include <utils/theme/theme.h>
@@ -43,9 +45,6 @@ namespace Internal {
const char SETTINGS_KEY[] = "ProjectExplorer/CompileOutput/Zoom";
const char C_COMPILE_OUTPUT[] = "ProjectExplorer.CompileOutput";
-const char POP_UP_KEY[] = "ProjectExplorer/Settings/ShowCompilerOutput";
-const char WRAP_OUTPUT_KEY[] = "ProjectExplorer/Settings/WrapBuildOutput";
-const char MAX_LINES_KEY[] = "ProjectExplorer/Settings/MaxBuildOutputLines";
const char OPTIONS_PAGE_ID[] = "C.ProjectExplorer.CompileOutputOptions";
CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
@@ -101,8 +100,17 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
Tr::tr("O"));
ExtensionSystem::PluginManager::addObject(m_handler);
setupContext(C_COMPILE_OUTPUT, m_outputWindow);
- loadSettings();
updateFromSettings();
+
+ m_outputWindow->setWordWrapEnabled(m_settings.wrapOutput());
+ m_outputWindow->setMaxCharCount(m_settings.maxCharCount());
+
+ connect(&m_settings.wrapOutput, &Utils::BaseAspect::changed, m_outputWindow, [this] {
+ m_outputWindow->setWordWrapEnabled(m_settings.wrapOutput());
+ });
+ connect(&m_settings.maxCharCount, &Utils::BaseAspect::changed, m_outputWindow, [this] {
+ m_outputWindow->setMaxCharCount(m_settings.maxCharCount());
+ });
}
CompileOutputWindow::~CompileOutputWindow()
@@ -115,10 +123,7 @@ CompileOutputWindow::~CompileOutputWindow()
void CompileOutputWindow::updateFromSettings()
{
- m_outputWindow->setWordWrapEnabled(m_settings.wrapOutput);
- m_outputWindow->setMaxCharCount(m_settings.maxCharCount);
}
-
bool CompileOutputWindow::hasFocus() const
{
return m_outputWindow->window()->focusWidget() == m_outputWindow;
@@ -213,13 +218,6 @@ void CompileOutputWindow::reset()
m_outputWindow->reset();
}
-void CompileOutputWindow::setSettings(const CompileOutputSettings &settings)
-{
- m_settings = settings;
- storeSettings();
- updateFromSettings();
-}
-
Utils::OutputFormatter *CompileOutputWindow::outputFormatter() const
{
return m_outputWindow->outputFormatter();
@@ -231,75 +229,49 @@ void CompileOutputWindow::updateFilter()
filterUsesRegexp(), filterIsInverted());
}
-const bool kPopUpDefault = false;
-const bool kWrapOutputDefault = true;
+// CompileOutputSettings
-void CompileOutputWindow::loadSettings()
-{
- QSettings * const s = Core::ICore::settings();
- m_settings.popUp = s->value(POP_UP_KEY, kPopUpDefault).toBool();
- m_settings.wrapOutput = s->value(WRAP_OUTPUT_KEY, kWrapOutputDefault).toBool();
- m_settings.maxCharCount = s->value(MAX_LINES_KEY,
- Core::Constants::DEFAULT_MAX_CHAR_COUNT).toInt() * 100;
-}
+static CompileOutputSettings *s_compileOutputSettings;
-void CompileOutputWindow::storeSettings() const
+CompileOutputSettings &CompileOutputSettings::instance()
{
- Utils::QtcSettings *const s = Core::ICore::settings();
- s->setValueWithDefault(POP_UP_KEY, m_settings.popUp, kPopUpDefault);
- s->setValueWithDefault(WRAP_OUTPUT_KEY, m_settings.wrapOutput, kWrapOutputDefault);
- s->setValueWithDefault(MAX_LINES_KEY,
- m_settings.maxCharCount / 100,
- Core::Constants::DEFAULT_MAX_CHAR_COUNT);
+ return *s_compileOutputSettings;
}
-class CompileOutputSettingsWidget : public Core::IOptionsPageWidget
+CompileOutputSettings::CompileOutputSettings()
{
-public:
- CompileOutputSettingsWidget()
- {
- const CompileOutputSettings &settings = BuildManager::compileOutputSettings();
- m_wrapOutputCheckBox.setText(Tr::tr("Word-wrap output"));
- m_wrapOutputCheckBox.setChecked(settings.wrapOutput);
- m_popUpCheckBox.setText(Tr::tr("Open Compile Output when building"));
- m_popUpCheckBox.setChecked(settings.popUp);
- m_maxCharsBox.setMaximum(100000000);
- m_maxCharsBox.setValue(settings.maxCharCount);
- const auto layout = new QVBoxLayout(this);
- layout->addWidget(&m_wrapOutputCheckBox);
- layout->addWidget(&m_popUpCheckBox);
- const auto maxCharsLayout = new QHBoxLayout;
- const QString msg = Tr::tr("Limit output to %1 characters");
- const QStringList parts = msg.split("%1") << QString() << QString();
- maxCharsLayout->addWidget(new QLabel(parts.at(0).trimmed()));
- maxCharsLayout->addWidget(&m_maxCharsBox);
- maxCharsLayout->addWidget(new QLabel(parts.at(1).trimmed()));
- maxCharsLayout->addStretch(1);
- layout->addLayout(maxCharsLayout);
- layout->addStretch(1);
- }
-
- void apply() final
- {
- CompileOutputSettings s;
- s.wrapOutput = m_wrapOutputCheckBox.isChecked();
- s.popUp = m_popUpCheckBox.isChecked();
- s.maxCharCount = m_maxCharsBox.value();
- BuildManager::setCompileOutputSettings(s);
- }
-
-private:
- QCheckBox m_wrapOutputCheckBox;
- QCheckBox m_popUpCheckBox;
- QSpinBox m_maxCharsBox;
-};
+ s_compileOutputSettings = this;
-CompileOutputSettingsPage::CompileOutputSettingsPage()
-{
setId(OPTIONS_PAGE_ID);
setDisplayName(Tr::tr("Compile Output"));
setCategory(Constants::BUILD_AND_RUN_SETTINGS_CATEGORY);
- setWidgetCreator([] { return new CompileOutputSettingsWidget; });
+
+ wrapOutput.setSettingsKey("ProjectExplorer/Settings/WrapBuildOutput");
+ wrapOutput.setDefaultValue(true);
+ wrapOutput.setLabelText(Tr::tr("Word-wrap output"));
+
+ popUp.setSettingsKey("ProjectExplorer/Settings/ShowCompilerOutput");
+ popUp.setLabelText(Tr::tr("Open Compile Output when building"));
+
+ maxCharCount.setSettingsKey("ProjectExplorer/Settings/MaxBuildOutputLines");
+ maxCharCount.setRange(1, Core::Constants::DEFAULT_MAX_CHAR_COUNT);
+ maxCharCount.setDefaultValue(Core::Constants::DEFAULT_MAX_CHAR_COUNT);
+ maxCharCount.setToSettingsTransformation([](const QVariant &v) { return v.toInt() / 100; });
+ maxCharCount.setFromSettingsTransformation([](const QVariant &v) { return v.toInt() * 100; });
+
+ setLayouter([this] {
+ using namespace Layouting;
+ const QString msg = Tr::tr("Limit output to %1 characters");
+ const QStringList parts = msg.split("%1") << QString() << QString();
+ return Column {
+ wrapOutput,
+ popUp,
+ Row { parts.at(0), maxCharCount, parts.at(1), st },
+ st
+ };
+ });
+
+ readSettings();
}
} // Internal
diff --git a/src/plugins/projectexplorer/compileoutputwindow.h b/src/plugins/projectexplorer/compileoutputwindow.h
index e1f000de9a..89c7b749f2 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.h
+++ b/src/plugins/projectexplorer/compileoutputwindow.h
@@ -26,6 +26,18 @@ namespace Internal {
class ShowOutputTaskHandler;
class CompileOutputTextEdit;
+class CompileOutputSettings final : public Core::PagedSettings
+{
+public:
+ CompileOutputSettings();
+
+ static CompileOutputSettings &instance();
+
+ Utils::BoolAspect popUp{this};
+ Utils::BoolAspect wrapOutput{this};
+ Utils::IntegerAspect maxCharCount{this};
+};
+
class CompileOutputWindow final : public Core::IOutputPane
{
Q_OBJECT
@@ -57,19 +69,13 @@ public:
void flush();
void reset();
- const CompileOutputSettings &settings() const { return m_settings; }
- void setSettings(const CompileOutputSettings &settings);
-
Utils::OutputFormatter *outputFormatter() const;
private:
void updateFilter() override;
const QList<Core::OutputWindow *> outputWindows() const override { return {m_outputWindow}; }
- void loadSettings();
- void storeSettings() const;
void updateFromSettings();
-
Core::OutputWindow *m_outputWindow;
ShowOutputTaskHandler *m_handler;
QToolButton *m_cancelBuildButton;
@@ -77,11 +83,5 @@ private:
CompileOutputSettings m_settings;
};
-class CompileOutputSettingsPage final : public Core::IOptionsPage
-{
-public:
- CompileOutputSettingsPage();
-};
-
} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/copystep.cpp b/src/plugins/projectexplorer/copystep.cpp
new file mode 100644
index 0000000000..db3b16098e
--- /dev/null
+++ b/src/plugins/projectexplorer/copystep.cpp
@@ -0,0 +1,114 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "copystep.h"
+
+#include "projectexplorerconstants.h"
+#include "projectexplorertr.h"
+
+#include <utils/aspects.h>
+
+using namespace Utils;
+
+namespace ProjectExplorer::Internal {
+
+const char SOURCE_KEY[] = "ProjectExplorer.CopyStep.Source";
+const char TARGET_KEY[] = "ProjectExplorer.CopyStep.Target";
+
+class CopyStepBase : public BuildStep
+{
+public:
+ CopyStepBase(BuildStepList *bsl, Id id)
+ : BuildStep(bsl, id)
+ {
+ m_sourceAspect.setSettingsKey(SOURCE_KEY);
+ m_sourceAspect.setLabelText(Tr::tr("Source:"));
+
+ m_targetAspect.setSettingsKey(TARGET_KEY);
+ m_targetAspect.setLabelText(Tr::tr("Target:"));
+
+ addMacroExpander();
+ }
+
+protected:
+ bool init() final
+ {
+ m_source = m_sourceAspect();
+ m_target = m_targetAspect();
+ return m_source.exists();
+ }
+
+ void doRun() final
+ {
+ // FIXME: asyncCopy does not handle directories yet.
+ QTC_ASSERT(m_source.isFile(), emit finished(false));
+ m_source.asyncCopy(m_target, this, [this](const expected_str<void> &cont) {
+ if (!cont) {
+ addOutput(cont.error(), OutputFormat::ErrorMessage);
+ addOutput(Tr::tr("Copying failed"), OutputFormat::ErrorMessage);
+ emit finished(false);
+ } else {
+ addOutput(Tr::tr("Copying finished"), OutputFormat::NormalMessage);
+ emit finished(true);
+ }
+ });
+ }
+
+ FilePathAspect m_sourceAspect{this};
+ FilePathAspect m_targetAspect{this};
+
+private:
+ FilePath m_source;
+ FilePath m_target;
+};
+
+class CopyFileStep final : public CopyStepBase
+{
+public:
+ CopyFileStep(BuildStepList *bsl, Id id)
+ : CopyStepBase(bsl, id)
+ {
+ // Expected kind could be stricter in theory, but since this here is
+ // a last stand fallback, better not impose extra "nice to have"
+ // work on the system.
+ m_sourceAspect.setExpectedKind(PathChooser::Any); // "File"
+ m_targetAspect.setExpectedKind(PathChooser::Any); // "SaveFile"
+
+ setSummaryUpdater([] {
+ return QString("<b>" + Tr::tr("Copy file") + "</b>");
+ });
+ }
+};
+
+class CopyDirectoryStep final : public CopyStepBase
+{
+public:
+ CopyDirectoryStep(BuildStepList *bsl, Id id)
+ : CopyStepBase(bsl, id)
+ {
+ m_sourceAspect.setExpectedKind(PathChooser::Directory);
+ m_targetAspect.setExpectedKind(PathChooser::Directory);
+
+ setSummaryUpdater([] {
+ return QString("<b>" + Tr::tr("Copy directory recursively") + "</b>");
+ });
+ }
+};
+
+// Factories
+
+CopyFileStepFactory::CopyFileStepFactory()
+{
+ registerStep<CopyFileStep>(Constants::COPY_FILE_STEP);
+ //: Default CopyStep display name
+ setDisplayName(Tr::tr("Copy file"));
+}
+
+CopyDirectoryStepFactory::CopyDirectoryStepFactory()
+{
+ registerStep<CopyDirectoryStep>(Constants::COPY_DIRECTORY_STEP);
+ //: Default CopyStep display name
+ setDisplayName(Tr::tr("Copy directory recursively"));
+}
+
+} // ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/copystep.h b/src/plugins/projectexplorer/copystep.h
new file mode 100644
index 0000000000..07940f3a89
--- /dev/null
+++ b/src/plugins/projectexplorer/copystep.h
@@ -0,0 +1,22 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "buildstep.h"
+
+namespace ProjectExplorer::Internal {
+
+class CopyFileStepFactory final : public BuildStepFactory
+{
+public:
+ CopyFileStepFactory();
+};
+
+class CopyDirectoryStepFactory final : public BuildStepFactory
+{
+public:
+ CopyDirectoryStepFactory();
+};
+
+} // ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/currentprojectfilter.cpp b/src/plugins/projectexplorer/currentprojectfilter.cpp
index 69b88ddf46..d0f9ed99b0 100644
--- a/src/plugins/projectexplorer/currentprojectfilter.cpp
+++ b/src/plugins/projectexplorer/currentprojectfilter.cpp
@@ -7,42 +7,28 @@
#include "projectexplorertr.h"
#include "projecttree.h"
-#include <utils/algorithm.h>
-
using namespace Core;
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
+using namespace Utils;
CurrentProjectFilter::CurrentProjectFilter()
- : BaseFileFilter()
{
setId("Files in current project");
setDisplayName(Tr::tr("Files in Current Project"));
- setDescription(Tr::tr("Matches all files from the current document's project. Append \"+<number>\" "
- "or \":<number>\" to jump to the given line number. Append another "
- "\"+<number>\" or \":<number>\" to jump to the column number as well."));
+ setDescription(Tr::tr("Locates files from the current document's project. Append \"+<number>\" "
+ "or \":<number>\" to jump to the given line number. Append another "
+ "\"+<number>\" or \":<number>\" to jump to the column number as well."));
setDefaultShortcutString("p");
- setDefaultIncludedByDefault(false);
+ setRefreshRecipe(Tasking::Sync([this] { invalidate(); }));
connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged,
this, &CurrentProjectFilter::currentProjectChanged);
-}
-
-void CurrentProjectFilter::markFilesAsOutOfDate()
-{
- setFileIterator(nullptr);
-}
-void CurrentProjectFilter::prepareSearch(const QString &entry)
-{
- Q_UNUSED(entry)
- if (!fileIterator()) {
- Utils::FilePaths paths;
- if (m_project)
- paths = m_project->files(Project::SourceFiles);
- setFileIterator(new BaseFileFilter::ListIterator(paths));
- }
- BaseFileFilter::prepareSearch(entry);
+ m_cache.setGeneratorProvider([this] {
+ const FilePaths paths = m_project ? m_project->files(Project::SourceFiles) : FilePaths();
+ return LocatorFileCache::filePathsGenerator(paths);
+ });
}
void CurrentProjectFilter::currentProjectChanged()
@@ -50,21 +36,12 @@ void CurrentProjectFilter::currentProjectChanged()
Project *project = ProjectTree::currentProject();
if (project == m_project)
return;
- if (m_project)
- disconnect(m_project, &Project::fileListChanged,
- this, &CurrentProjectFilter::markFilesAsOutOfDate);
-
- if (project)
- connect(project, &Project::fileListChanged,
- this, &CurrentProjectFilter::markFilesAsOutOfDate);
+ if (m_project)
+ disconnect(m_project, &Project::fileListChanged, this, &CurrentProjectFilter::invalidate);
m_project = project;
- markFilesAsOutOfDate();
-}
+ if (m_project)
+ connect(m_project, &Project::fileListChanged, this, &CurrentProjectFilter::invalidate);
-void CurrentProjectFilter::refresh(QFutureInterface<void> &future)
-{
- Q_UNUSED(future)
- QMetaObject::invokeMethod(this, &CurrentProjectFilter::markFilesAsOutOfDate,
- Qt::QueuedConnection);
+ invalidate();
}
diff --git a/src/plugins/projectexplorer/currentprojectfilter.h b/src/plugins/projectexplorer/currentprojectfilter.h
index b9d63db293..6c50070790 100644
--- a/src/plugins/projectexplorer/currentprojectfilter.h
+++ b/src/plugins/projectexplorer/currentprojectfilter.h
@@ -3,31 +3,24 @@
#pragma once
-#include <coreplugin/locator/basefilefilter.h>
+#include <coreplugin/locator/ilocatorfilter.h>
-#include <QFutureInterface>
+namespace ProjectExplorer { class Project; }
-namespace ProjectExplorer {
+namespace ProjectExplorer::Internal {
-class Project;
-
-namespace Internal {
-
-class CurrentProjectFilter : public Core::BaseFileFilter
+class CurrentProjectFilter : public Core::ILocatorFilter
{
- Q_OBJECT
-
public:
CurrentProjectFilter();
- void refresh(QFutureInterface<void> &future) override;
- void prepareSearch(const QString &entry) override;
private:
+ Core::LocatorMatcherTasks matchers() final { return {m_cache.matcher()}; }
void currentProjectChanged();
- void markFilesAsOutOfDate();
+ void invalidate() { m_cache.invalidate(); }
+ Core::LocatorFileCache m_cache;
Project *m_project = nullptr;
};
-} // namespace Internal
-} // namespace ProjectExplorer
+} // namespace ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/currentprojectfind.cpp b/src/plugins/projectexplorer/currentprojectfind.cpp
index 7ecbd99069..3bde2bb62f 100644
--- a/src/plugins/projectexplorer/currentprojectfind.cpp
+++ b/src/plugins/projectexplorer/currentprojectfind.cpp
@@ -5,8 +5,8 @@
#include "project.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projecttree.h"
-#include "session.h"
#include <utils/qtcassert.h>
#include <utils/filesearch.h>
@@ -23,7 +23,7 @@ CurrentProjectFind::CurrentProjectFind()
{
connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged,
this, &CurrentProjectFind::handleProjectChanged);
- connect(SessionManager::instance(), &SessionManager::projectDisplayNameChanged,
+ connect(ProjectManager::instance(), &ProjectManager::projectDisplayNameChanged,
this, [this](ProjectExplorer::Project *p) {
if (p == ProjectTree::currentProject())
emit displayNameChanged();
@@ -61,14 +61,13 @@ FileIterator *CurrentProjectFind::files(const QStringList &nameFilters,
const QStringList &exclusionFilters,
const QVariant &additionalParameters) const
{
- QTC_ASSERT(additionalParameters.isValid(),
- return new FileListIterator(FilePaths(), QList<QTextCodec *>()));
+ QTC_ASSERT(additionalParameters.isValid(), return new FileListIterator);
const FilePath projectFile = FilePath::fromVariant(additionalParameters);
- for (Project *project : SessionManager::projects()) {
+ for (Project *project : ProjectManager::projects()) {
if (project && projectFile == project->projectFilePath())
return filesForProjects(nameFilters, exclusionFilters, {project});
}
- return new FileListIterator(FilePaths(), QList<QTextCodec *>());
+ return new FileListIterator;
}
QString CurrentProjectFind::label() const
@@ -87,7 +86,7 @@ void CurrentProjectFind::handleProjectChanged()
void CurrentProjectFind::recheckEnabled(Core::SearchResult *search)
{
const FilePath projectFile = FilePath::fromVariant(getAdditionalParameters(search));
- for (Project *project : SessionManager::projects()) {
+ for (Project *project : ProjectManager::projects()) {
if (projectFile == project->projectFilePath()) {
search->setSearchAgainEnabled(true);
return;
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
index 9d25bb7dfe..00f7225d0d 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
@@ -3,7 +3,6 @@
#include "customexecutablerunconfiguration.h"
-#include "localenvironmentaspect.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
#include "runconfigurationaspects.h"
@@ -24,7 +23,8 @@ CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *targe
CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id)
{
- auto envAspect = addAspect<LocalEnvironmentAspect>(target);
+ auto envAspect = addAspect<EnvironmentAspect>();
+ envAspect->setSupportForBuildEnvironment(target);
auto exeAspect = addAspect<ExecutableAspect>(target, ExecutableAspect::HostDevice);
exeAspect->setSettingsKey("ProjectExplorer.CustomExecutableRunConfiguration.Executable");
diff --git a/src/plugins/projectexplorer/customparserconfigdialog.cpp b/src/plugins/projectexplorer/customparserconfigdialog.cpp
index 4ebc880c14..cbfd1adfbc 100644
--- a/src/plugins/projectexplorer/customparserconfigdialog.cpp
+++ b/src/plugins/projectexplorer/customparserconfigdialog.cpp
@@ -101,7 +101,7 @@ CustomParserConfigDialog::CustomParserConfigDialog(QWidget *parent)
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
- using namespace Utils::Layouting;
+ using namespace Layouting;
auto tabWarning = new QWidget;
Column {
diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
index f2b33378b5..7d1174839d 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
@@ -8,7 +8,7 @@
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
-#include <utils/qtcprocess.h>
+#include <utils/process.h>
#include <utils/temporarydirectory.h>
#include <QFileInfo>
@@ -64,7 +64,7 @@ static bool
const QMap<QString, QString> &fieldMap,
QString *stdOut /* = 0 */, QString *errorMessage)
{
- Utils::QtcProcess process;
+ Utils::Process process;
const QString binary = script.front();
QStringList arguments;
const int binarySize = script.size();
diff --git a/src/plugins/projectexplorer/dependenciespanel.cpp b/src/plugins/projectexplorer/dependenciespanel.cpp
index 1799126a5b..daac52b8d7 100644
--- a/src/plugins/projectexplorer/dependenciespanel.cpp
+++ b/src/plugins/projectexplorer/dependenciespanel.cpp
@@ -5,9 +5,10 @@
#include "project.h"
#include "projectexplorertr.h"
-#include "session.h"
+#include "projectmanager.h"
#include <coreplugin/icore.h>
+#include <coreplugin/session.h>
#include <utils/algorithm.h>
#include <utils/detailswidget.h>
@@ -32,19 +33,18 @@ DependenciesModel::DependenciesModel(Project *project, QObject *parent)
{
resetModel();
- SessionManager *sessionManager = SessionManager::instance();
- connect(sessionManager, &SessionManager::projectRemoved,
+ connect(ProjectManager::instance(), &ProjectManager::projectRemoved,
this, &DependenciesModel::resetModel);
- connect(sessionManager, &SessionManager::projectAdded,
+ connect(ProjectManager::instance(), &ProjectManager::projectAdded,
this, &DependenciesModel::resetModel);
- connect(sessionManager, &SessionManager::sessionLoaded,
+ connect(Core::SessionManager::instance(), &Core::SessionManager::sessionLoaded,
this, &DependenciesModel::resetModel);
}
void DependenciesModel::resetModel()
{
beginResetModel();
- m_projects = SessionManager::projects();
+ m_projects = ProjectManager::projects();
m_projects.removeAll(m_project);
Utils::sort(m_projects, [](Project *a, Project *b) {
return a->displayName() < b->displayName();
@@ -77,7 +77,7 @@ QVariant DependenciesModel::data(const QModelIndex &index, int role) const
case Qt::ToolTipRole:
return p->projectFilePath().toUserOutput();
case Qt::CheckStateRole:
- return SessionManager::hasDependency(m_project, p) ? Qt::Checked : Qt::Unchecked;
+ return ProjectManager::hasDependency(m_project, p) ? Qt::Checked : Qt::Unchecked;
case Qt::DecorationRole:
return Utils::FileIconProvider::icon(p->projectFilePath());
default:
@@ -92,7 +92,7 @@ bool DependenciesModel::setData(const QModelIndex &index, const QVariant &value,
const auto c = static_cast<Qt::CheckState>(value.toInt());
if (c == Qt::Checked) {
- if (SessionManager::addDependency(m_project, p)) {
+ if (ProjectManager::addDependency(m_project, p)) {
emit dataChanged(index, index);
return true;
} else {
@@ -100,8 +100,8 @@ bool DependenciesModel::setData(const QModelIndex &index, const QVariant &value,
Tr::tr("This would create a circular dependency."));
}
} else if (c == Qt::Unchecked) {
- if (SessionManager::hasDependency(m_project, p)) {
- SessionManager::removeDependency(m_project, p);
+ if (ProjectManager::hasDependency(m_project, p)) {
+ ProjectManager::removeDependency(m_project, p);
emit dataChanged(index, index);
return true;
}
@@ -215,9 +215,9 @@ DependenciesWidget::DependenciesWidget(Project *project, QWidget *parent) : Proj
m_cascadeSetActiveCheckBox = new QCheckBox;
m_cascadeSetActiveCheckBox->setText(Tr::tr("Synchronize configuration"));
m_cascadeSetActiveCheckBox->setToolTip(Tr::tr("Synchronize active kit, build, and deploy configuration between projects."));
- m_cascadeSetActiveCheckBox->setChecked(SessionManager::isProjectConfigurationCascading());
+ m_cascadeSetActiveCheckBox->setChecked(ProjectManager::isProjectConfigurationCascading());
connect(m_cascadeSetActiveCheckBox, &QCheckBox::toggled,
- SessionManager::instance(), &SessionManager::setProjectConfigurationCascading);
+ ProjectManager::instance(), &ProjectManager::setProjectConfigurationCascading);
layout->addWidget(m_cascadeSetActiveCheckBox, 1, 0, 2, 1);
}
diff --git a/src/plugins/projectexplorer/desktoprunconfiguration.cpp b/src/plugins/projectexplorer/desktoprunconfiguration.cpp
index 82d0123b11..8b8cdf2b79 100644
--- a/src/plugins/projectexplorer/desktoprunconfiguration.cpp
+++ b/src/plugins/projectexplorer/desktoprunconfiguration.cpp
@@ -4,7 +4,6 @@
#include "desktoprunconfiguration.h"
#include "buildsystem.h"
-#include "localenvironmentaspect.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
#include "runconfigurationaspects.h"
@@ -43,7 +42,8 @@ private:
DesktopRunConfiguration::DesktopRunConfiguration(Target *target, Id id, Kind kind)
: RunConfiguration(target, id), m_kind(kind)
{
- auto envAspect = addAspect<LocalEnvironmentAspect>(target);
+ auto envAspect = addAspect<EnvironmentAspect>();
+ envAspect->setSupportForBuildEnvironment(target);
addAspect<ExecutableAspect>(target, ExecutableAspect::RunDevice);
addAspect<ArgumentsAspect>(macroExpander());
@@ -87,7 +87,8 @@ void DesktopRunConfiguration::updateTargetInformation()
BuildTargetInfo bti = buildTargetInfo();
auto terminalAspect = aspect<TerminalAspect>();
- terminalAspect->setUseTerminalHint(bti.usesTerminal);
+ terminalAspect->setUseTerminalHint(bti.targetFilePath.needsDevice() ? false : bti.usesTerminal);
+ terminalAspect->setEnabled(!bti.targetFilePath.needsDevice());
if (m_kind == Qmake) {
@@ -121,7 +122,7 @@ void DesktopRunConfiguration::updateTargetInformation()
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
- emit aspect<LocalEnvironmentAspect>()->environmentChanged();
+ emit aspect<EnvironmentAspect>()->environmentChanged();
}
}
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
index a09c8bac76..099040d6b2 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp
@@ -3,11 +3,11 @@
#include "desktopdevice.h"
-#include "desktopprocesssignaloperation.h"
-#include "deviceprocesslist.h"
-#include "localprocesslist.h"
#include "../projectexplorerconstants.h"
#include "../projectexplorertr.h"
+#include "desktopprocesssignaloperation.h"
+#include "deviceprocesslist.h"
+#include "processlist.h"
#include <coreplugin/fileutils.h>
@@ -15,18 +15,19 @@
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/portlist.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <utils/terminalcommand.h>
+#include <utils/terminalhooks.h>
#include <utils/url.h>
#include <QCoreApplication>
#include <QDateTime>
#ifdef Q_OS_WIN
-#include <windows.h>
-#include <stdlib.h>
#include <cstring>
+#include <stdlib.h>
+#include <windows.h>
#endif
using namespace ProjectExplorer::Constants;
@@ -34,58 +35,11 @@ using namespace Utils;
namespace ProjectExplorer {
-static void startTerminalEmulator(const QString &workingDir, const Environment &env)
-{
-#ifdef Q_OS_WIN
- STARTUPINFO si;
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
-
- PROCESS_INFORMATION pinfo;
- ZeroMemory(&pinfo, sizeof(pinfo));
-
- static const auto quoteWinCommand = [](const QString &program) {
- const QChar doubleQuote = QLatin1Char('"');
-
- // add the program as the first arg ... it works better
- QString programName = program;
- programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
- if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote)
- && programName.contains(QLatin1Char(' '))) {
- programName.prepend(doubleQuote);
- programName.append(doubleQuote);
- }
- return programName;
- };
- const QString cmdLine = quoteWinCommand(qtcEnvironmentVariable("COMSPEC"));
- // cmdLine is assumed to be detached -
- // https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083
-
- const QString totalEnvironment = env.toStringList().join(QChar(QChar::Null)) + QChar(QChar::Null);
- LPVOID envPtr = (env != Environment::systemEnvironment())
- ? (WCHAR *)(totalEnvironment.utf16()) : nullptr;
-
- const bool success = CreateProcessW(0, (WCHAR *)cmdLine.utf16(),
- 0, 0, FALSE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
- envPtr, workingDir.isEmpty() ? 0 : (WCHAR *)workingDir.utf16(),
- &si, &pinfo);
-
- if (success) {
- CloseHandle(pinfo.hThread);
- CloseHandle(pinfo.hProcess);
- }
-#else
- const TerminalCommand term = TerminalCommand::terminalEmulator();
- QProcess process;
- process.setProgram(term.command.nativePath());
- process.setArguments(ProcessArgs::splitArgs(term.openArgs));
- process.setProcessEnvironment(env.toProcessEnvironment());
- process.setWorkingDirectory(workingDir);
- process.startDetached();
-#endif
-}
+class DesktopDevicePrivate : public QObject
+{};
DesktopDevice::DesktopDevice()
+ : d(new DesktopDevicePrivate())
{
setFileAccess(DesktopDeviceFileAccess::instance());
@@ -98,20 +52,26 @@ DesktopDevice::DesktopDevice()
setMachineType(IDevice::Hardware);
setOsType(HostOsInfo::hostOs());
- const QString portRange =
- QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END);
+ const QString portRange
+ = QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END);
setFreePorts(Utils::PortList::fromString(portRange));
setOpenTerminal([](const Environment &env, const FilePath &path) {
- const QFileInfo fileInfo = path.toFileInfo();
- const QString workingDir = QDir::toNativeSeparators(fileInfo.isDir() ?
- fileInfo.absoluteFilePath() :
- fileInfo.absolutePath());
const Environment realEnv = env.hasChanges() ? env : Environment::systemEnvironment();
- startTerminalEmulator(workingDir, realEnv);
+
+ const FilePath shell = Terminal::defaultShellForDevice(path);
+
+ Process process;
+ process.setTerminalMode(TerminalMode::Detached);
+ process.setEnvironment(realEnv);
+ process.setCommand({shell, {}});
+ process.setWorkingDirectory(path);
+ process.start();
});
}
+DesktopDevice::~DesktopDevice() = default;
+
IDevice::DeviceInfo DesktopDevice::deviceInformation() const
{
return DeviceInfo();
@@ -125,11 +85,6 @@ IDeviceWidget *DesktopDevice::createWidget()
// range can be confusing to the user. Hence, disabling the widget for now.
}
-bool DesktopDevice::canAutoDetectPorts() const
-{
- return true;
-}
-
bool DesktopDevice::canCreateProcessModel() const
{
return true;
@@ -137,7 +92,7 @@ bool DesktopDevice::canCreateProcessModel() const
DeviceProcessList *DesktopDevice::createProcessListModel(QObject *parent) const
{
- return new Internal::LocalProcessList(sharedFromThis(), parent);
+ return new ProcessList(sharedFromThis(), parent);
}
DeviceProcessSignalOperation::Ptr DesktopDevice::signalOperation() const
@@ -145,31 +100,6 @@ DeviceProcessSignalOperation::Ptr DesktopDevice::signalOperation() const
return DeviceProcessSignalOperation::Ptr(new DesktopProcessSignalOperation());
}
-PortsGatheringMethod DesktopDevice::portsGatheringMethod() const
-{
- return {
- [this](QAbstractSocket::NetworkLayerProtocol protocol) -> CommandLine {
- // We might encounter the situation that protocol is given IPv6
- // but the consumer of the free port information decides to open
- // an IPv4(only) port. As a result the next IPv6 scan will
- // report the port again as open (in IPv6 namespace), while the
- // same port in IPv4 namespace might still be blocked, and
- // re-use of this port fails.
- // GDBserver behaves exactly like this.
-
- Q_UNUSED(protocol)
-
- if (HostOsInfo::isWindowsHost() || HostOsInfo::isMacHost())
- return {filePath("netstat"), {"-a", "-n"}};
- if (HostOsInfo::isLinuxHost())
- return {filePath("/bin/sh"), {"-c", "cat /proc/net/tcp*"}};
- return {};
- },
-
- &Port::parseFromNetstatOutput
- };
-}
-
QUrl DesktopDevice::toolControlChannel(const ControlChannelHint &) const
{
QUrl url;
diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h
index ee5ac1ca5e..d9cafbfda9 100644
--- a/src/plugins/projectexplorer/devicesupport/desktopdevice.h
+++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.h
@@ -6,25 +6,27 @@
#include "../projectexplorer_export.h"
#include "idevice.h"
-#include "idevicefactory.h"
#include <QApplication>
+#include <memory>
+
namespace ProjectExplorer {
class ProjectExplorerPlugin;
+class DesktopDevicePrivate;
namespace Internal { class DesktopDeviceFactory; }
class PROJECTEXPLORER_EXPORT DesktopDevice : public IDevice
{
public:
+ ~DesktopDevice() override;
+
IDevice::DeviceInfo deviceInformation() const override;
IDeviceWidget *createWidget() override;
- bool canAutoDetectPorts() const override;
bool canCreateProcessModel() const override;
DeviceProcessList *createProcessListModel(QObject *parent) const override;
- ProjectExplorer::PortsGatheringMethod portsGatheringMethod() const override;
DeviceProcessSignalOperation::Ptr signalOperation() const override;
QUrl toolControlChannel(const ControlChannelHint &) const override;
bool usableAsBuildDevice() const override;
@@ -40,6 +42,8 @@ protected:
friend class ProjectExplorerPlugin;
friend class Internal::DesktopDeviceFactory;
+
+ std::unique_ptr<DesktopDevicePrivate> d;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp
index acce8bf29b..84e3b27408 100644
--- a/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.cpp
@@ -4,6 +4,7 @@
#include "devicecheckbuildstep.h"
#include "../kitinformation.h"
+#include "../projectexplorerconstants.h"
#include "../projectexplorertr.h"
#include "devicemanager.h"
@@ -12,60 +13,61 @@
#include <QMessageBox>
-using namespace ProjectExplorer;
+namespace ProjectExplorer {
-DeviceCheckBuildStep::DeviceCheckBuildStep(BuildStepList *bsl, Utils::Id id)
- : BuildStep(bsl, id)
+class DeviceCheckBuildStep : public BuildStep
{
- setWidgetExpandedByDefault(false);
-}
+public:
+ DeviceCheckBuildStep(BuildStepList *bsl, Utils::Id id)
+ : BuildStep(bsl, id)
+ {
+ setWidgetExpandedByDefault(false);
+ }
-bool DeviceCheckBuildStep::init()
-{
- IDevice::ConstPtr device = DeviceKitAspect::device(kit());
- if (!device) {
- Utils::Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(kit());
- IDeviceFactory *factory = IDeviceFactory::find(deviceTypeId);
- if (!factory || !factory->canCreate()) {
- emit addOutput(Tr::tr("No device configured."), BuildStep::OutputFormat::ErrorMessage);
- return false;
- }
+ bool init() override
+ {
+ IDevice::ConstPtr device = DeviceKitAspect::device(kit());
+ if (!device) {
+ Utils::Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(kit());
+ IDeviceFactory *factory = IDeviceFactory::find(deviceTypeId);
+ if (!factory || !factory->canCreate()) {
+ emit addOutput(Tr::tr("No device configured."), BuildStep::OutputFormat::ErrorMessage);
+ return false;
+ }
- QMessageBox msgBox(QMessageBox::Question, Tr::tr("Set Up Device"),
- Tr::tr("There is no device set up for this kit. Do you want to add a device?"),
- QMessageBox::Yes|QMessageBox::No);
- msgBox.setDefaultButton(QMessageBox::Yes);
- if (msgBox.exec() == QMessageBox::No) {
- emit addOutput(Tr::tr("No device configured."), BuildStep::OutputFormat::ErrorMessage);
- return false;
- }
+ QMessageBox msgBox(QMessageBox::Question, Tr::tr("Set Up Device"),
+ Tr::tr("There is no device set up for this kit. Do you want to add a device?"),
+ QMessageBox::Yes|QMessageBox::No);
+ msgBox.setDefaultButton(QMessageBox::Yes);
+ if (msgBox.exec() == QMessageBox::No) {
+ emit addOutput(Tr::tr("No device configured."), BuildStep::OutputFormat::ErrorMessage);
+ return false;
+ }
- IDevice::Ptr newDevice = factory->create();
- if (newDevice.isNull()) {
- emit addOutput(Tr::tr("No device configured."), BuildStep::OutputFormat::ErrorMessage);
- return false;
- }
+ IDevice::Ptr newDevice = factory->create();
+ if (newDevice.isNull()) {
+ emit addOutput(Tr::tr("No device configured."), BuildStep::OutputFormat::ErrorMessage);
+ return false;
+ }
- DeviceManager *dm = DeviceManager::instance();
- dm->addDevice(newDevice);
+ DeviceManager *dm = DeviceManager::instance();
+ dm->addDevice(newDevice);
- DeviceKitAspect::setDevice(kit(), newDevice);
+ DeviceKitAspect::setDevice(kit(), newDevice);
+ }
+
+ return true;
}
- return true;
-}
+ void doRun() override { emit finished(true); }
+};
-void DeviceCheckBuildStep::doRun()
-{
- emit finished(true);
-}
+// Factory
-Utils::Id DeviceCheckBuildStep::stepId()
+DeviceCheckBuildStepFactory::DeviceCheckBuildStepFactory()
{
- return "ProjectExplorer.DeviceCheckBuildStep";
+ registerStep<DeviceCheckBuildStep>(Constants::DEVICE_CHECK_STEP);
+ setDisplayName(Tr::tr("Check for a configured device"));
}
-QString DeviceCheckBuildStep::displayName()
-{
- return Tr::tr("Check for a configured device");
-}
+} // ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.h b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.h
index 8b7d3687b0..6b7a8edb11 100644
--- a/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.h
+++ b/src/plugins/projectexplorer/devicesupport/devicecheckbuildstep.h
@@ -8,18 +8,10 @@
namespace ProjectExplorer {
-class PROJECTEXPLORER_EXPORT DeviceCheckBuildStep : public BuildStep
+class PROJECTEXPLORER_EXPORT DeviceCheckBuildStepFactory : public BuildStepFactory
{
- Q_OBJECT
-
public:
- DeviceCheckBuildStep(BuildStepList *bsl, Utils::Id id);
-
- bool init() override;
- void doRun() override;
-
- static Utils::Id stepId();
- static QString displayName();
+ DeviceCheckBuildStepFactory();
};
-} // namespace ProjectExplorer
+} // ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.cpp b/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.cpp
index ed47999432..987f2e0c39 100644
--- a/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.cpp
@@ -24,7 +24,7 @@ DeviceFactorySelectionDialog::DeviceFactorySelectionDialog(QWidget *parent) :
m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
m_buttonBox->button(QDialogButtonBox::Ok)->setText(Tr::tr("Start Wizard"));
- using namespace Utils::Layouting;
+ using namespace Layouting;
Column {
Tr::tr("Available device types:"),
m_listWidget,
diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
index 9f8e0594fd..aa017df46b 100644
--- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp
@@ -14,9 +14,10 @@
#include <utils/environment.h>
#include <utils/fsengine/fsengine.h>
#include <utils/persistentsettings.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
+#include <utils/terminalhooks.h>
#include <QHash>
#include <QMutex>
@@ -442,6 +443,13 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
device->openTerminal(env, filePath);
};
+ deviceHooks.osType = [](const FilePath &filePath) {
+ auto device = DeviceManager::deviceForPath(filePath);
+ if (!device)
+ return OsTypeLinux;
+ return device->osType();
+ };
+
DeviceProcessHooks processHooks;
processHooks.processImplHook = [](const FilePath &filePath) -> ProcessInterface * {
@@ -456,7 +464,23 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
return device->systemEnvironment();
};
- QtcProcess::setRemoteProcessHooks(processHooks);
+ Process::setRemoteProcessHooks(processHooks);
+
+ Terminal::Hooks::instance().getTerminalCommandsForDevicesHook().set(
+ [this]() -> QList<Terminal::NameAndCommandLine> {
+ QList<Terminal::NameAndCommandLine> result;
+ for (const IDevice::ConstPtr device : d->devices) {
+ if (device->type() == Constants::DESKTOP_DEVICE_TYPE)
+ continue;
+
+ const FilePath shell = Terminal::defaultShellForDevice(device->rootPath());
+
+ if (!shell.isEmpty())
+ result << Terminal::NameAndCommandLine{device->displayName(),
+ CommandLine{shell, {}}};
+ }
+ return result;
+ });
}
DeviceManager::~DeviceManager()
diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
index 39af471345..a35387a3c2 100644
--- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
@@ -17,13 +17,16 @@
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
+#include <utils/async.h>
#include <utils/layoutbuilder.h>
+#include <utils/optionpushbutton.h>
#include <utils/qtcassert.h>
#include <QComboBox>
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
+#include <QMenu>
#include <QPushButton>
#include <QScrollArea>
#include <QTextStream>
@@ -100,21 +103,47 @@ void DeviceSettingsWidget::initGui()
m_deviceStateTextLabel = new QLabel;
m_osSpecificGroupBox = new QGroupBox(Tr::tr("Type Specific"));
m_osSpecificGroupBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
- m_addConfigButton = new QPushButton(Tr::tr("&Add..."));
m_removeConfigButton = new QPushButton(Tr::tr("&Remove"));
m_defaultDeviceButton = new QPushButton(Tr::tr("Set As Default"));
- auto line = new QFrame;
- line->setFrameShape(QFrame::HLine);
- line->setFrameShadow(QFrame::Sunken);
- auto customButtonsContainer = new QWidget;
- m_buttonsLayout = new QVBoxLayout(customButtonsContainer);
+
+ OptionPushButton *addButton = new OptionPushButton(Tr::tr("&Add..."));
+ connect(addButton, &OptionPushButton::clicked, this, &DeviceSettingsWidget::addDevice);
+
+ QMenu *deviceTypeMenu = new QMenu(addButton);
+ QAction *defaultAction = new QAction(Tr::tr("&Start Wizard to Add Device..."));
+ connect(defaultAction, &QAction::triggered, this, &DeviceSettingsWidget::addDevice);
+ deviceTypeMenu->addAction(defaultAction);
+ deviceTypeMenu->addSeparator();
+
+ for (IDeviceFactory *factory : IDeviceFactory::allDeviceFactories()) {
+ if (!factory->canCreate())
+ continue;
+ if (!factory->quickCreationAllowed())
+ continue;
+
+ QAction *action = new QAction(Tr::tr("Add %1").arg(factory->displayName()));
+ deviceTypeMenu->addAction(action);
+
+ connect(action, &QAction::triggered, this, [factory, this] {
+ IDevice::Ptr device = factory->construct();
+ QTC_ASSERT(device, return);
+ m_deviceManager->addDevice(device);
+ m_removeConfigButton->setEnabled(true);
+ m_configurationComboBox->setCurrentIndex(m_deviceManagerModel->indexOf(device));
+ saveSettings();
+ });
+ }
+
+ addButton->setOptionalMenu(deviceTypeMenu);
+
+ m_buttonsLayout = new QVBoxLayout;
m_buttonsLayout->setContentsMargins({});
auto scrollAreaWidget = new QWidget;
auto scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(scrollAreaWidget);
- using namespace Utils::Layouting;
+ using namespace Layouting;
Column {
m_generalGroupBox,
m_osSpecificGroupBox,
@@ -127,25 +156,27 @@ void DeviceSettingsWidget::initGui()
Tr::tr("Current state:"), Row { m_deviceStateIconLabel, m_deviceStateTextLabel, st, }, br,
}.attachTo(m_generalGroupBox);
+ // clang-format off
Row {
Column {
Form { m_configurationLabel, m_configurationComboBox, br, },
scrollArea,
},
Column {
- m_addConfigButton,
+ addButton,
+ Space(30),
m_removeConfigButton,
m_defaultDeviceButton,
- line,
- customButtonsContainer,
+ m_buttonsLayout,
st,
},
}.attachTo(this);
+ // clang-format on
bool hasDeviceFactories = Utils::anyOf(IDeviceFactory::allDeviceFactories(),
&IDeviceFactory::canCreate);
- m_addConfigButton->setEnabled(hasDeviceFactories);
+ addButton->setEnabled(hasDeviceFactories);
int lastIndex = ICore::settings()
->value(QLatin1String(LastDeviceIndexKey), 0).toInt();
@@ -160,10 +191,10 @@ void DeviceSettingsWidget::initGui()
this, &DeviceSettingsWidget::setDefaultDevice);
connect(m_removeConfigButton, &QAbstractButton::clicked,
this, &DeviceSettingsWidget::removeDevice);
- connect(m_nameLineEdit, &QLineEdit::editingFinished,
- this, &DeviceSettingsWidget::deviceNameEditingFinished);
- connect(m_addConfigButton, &QAbstractButton::clicked,
- this, &DeviceSettingsWidget::addDevice);
+ connect(m_nameLineEdit,
+ &QLineEdit::editingFinished,
+ this,
+ &DeviceSettingsWidget::deviceNameEditingFinished);
}
void DeviceSettingsWidget::addDevice()
@@ -182,6 +213,8 @@ void DeviceSettingsWidget::addDevice()
if (device.isNull())
return;
+ Utils::asyncRun([device] { device->checkOsType(); });
+
m_deviceManager->addDevice(device);
m_removeConfigButton->setEnabled(true);
m_configurationComboBox->setCurrentIndex(m_deviceManagerModel->indexOf(device));
diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
index 5cd5cec85e..207b60cf74 100644
--- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
+++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
@@ -76,7 +76,6 @@ private:
QLabel *m_deviceStateIconLabel;
QLabel *m_deviceStateTextLabel;
QGroupBox *m_osSpecificGroupBox;
- QPushButton *m_addConfigButton;
QPushButton *m_removeConfigButton;
QPushButton *m_defaultDeviceButton;
QVBoxLayout *m_buttonsLayout;
diff --git a/src/plugins/projectexplorer/devicesupport/devicetestdialog.cpp b/src/plugins/projectexplorer/devicesupport/devicetestdialog.cpp
index 91a83531b4..0277fc827a 100644
--- a/src/plugins/projectexplorer/devicesupport/devicetestdialog.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicetestdialog.cpp
@@ -43,7 +43,7 @@ DeviceTestDialog::DeviceTestDialog(const IDevice::Ptr &deviceConfiguration,
d->textEdit->setReadOnly(true);
d->buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel);
- using namespace Utils::Layouting;
+ using namespace Layouting;
Column {
d->textEdit,
d->buttonBox,
diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
index 8081c9745d..c3f3f195ca 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
+++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
@@ -9,8 +9,8 @@
#include <utils/port.h>
#include <utils/portlist.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <utils/url.h>
@@ -22,7 +22,7 @@ namespace Internal {
class DeviceUsedPortsGathererPrivate
{
public:
- std::unique_ptr<QtcProcess> process;
+ std::unique_ptr<Process> process;
QList<Port> usedPorts;
IDevice::ConstPtr device;
PortsGatheringMethod portsGatheringMethod;
@@ -54,10 +54,10 @@ void DeviceUsedPortsGatherer::start()
const QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::AnyIPProtocol;
- d->process.reset(new QtcProcess);
+ d->process.reset(new Process);
d->process->setCommand(d->portsGatheringMethod.commandLine(protocol));
- connect(d->process.get(), &QtcProcess::done, this, &DeviceUsedPortsGatherer::handleProcessDone);
+ connect(d->process.get(), &Process::done, this, &DeviceUsedPortsGatherer::handleProcessDone);
d->process->start();
}
@@ -116,12 +116,6 @@ void DeviceUsedPortsGatherer::handleProcessDone()
stop();
}
-DeviceUsedPortsGathererAdapter::DeviceUsedPortsGathererAdapter()
-{
- connect(task(), &DeviceUsedPortsGatherer::portListReady, this, [this] { emit done(true); });
- connect(task(), &DeviceUsedPortsGatherer::error, this, [this] { emit done(false); });
-}
-
// PortGatherer
PortsGatherer::PortsGatherer(RunControl *runControl)
diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
index 3519c7d22f..20b0c9c9e8 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
+++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.h
@@ -7,8 +7,9 @@
#include <projectexplorer/runcontrol.h>
+#include <solutions/tasking/tasktree.h>
+
#include <utils/portlist.h>
-#include <utils/tasktree.h>
namespace ProjectExplorer {
@@ -43,11 +44,14 @@ private:
Internal::DeviceUsedPortsGathererPrivate * const d;
};
-class PROJECTEXPLORER_EXPORT DeviceUsedPortsGathererAdapter
- : public Utils::Tasking::TaskAdapter<DeviceUsedPortsGatherer>
+class PROJECTEXPLORER_EXPORT DeviceUsedPortsGathererTaskAdapter
+ : public Tasking::TaskAdapter<DeviceUsedPortsGatherer>
{
public:
- DeviceUsedPortsGathererAdapter();
+ DeviceUsedPortsGathererTaskAdapter() {
+ connect(task(), &DeviceUsedPortsGatherer::portListReady, this, [this] { emit done(true); });
+ connect(task(), &DeviceUsedPortsGatherer::error, this, [this] { emit done(false); });
+ }
void start() final { task()->start(); }
};
@@ -85,4 +89,5 @@ private:
} // namespace ProjectExplorer
-QTC_DECLARE_CUSTOM_TASK(PortGatherer, ProjectExplorer::DeviceUsedPortsGathererAdapter);
+TASKING_DECLARE_TASK(DeviceUsedPortsGathererTask,
+ ProjectExplorer::DeviceUsedPortsGathererTaskAdapter);
diff --git a/src/plugins/projectexplorer/devicesupport/filetransfer.cpp b/src/plugins/projectexplorer/devicesupport/filetransfer.cpp
index bd386db0d1..0581579767 100644
--- a/src/plugins/projectexplorer/devicesupport/filetransfer.cpp
+++ b/src/plugins/projectexplorer/devicesupport/filetransfer.cpp
@@ -16,43 +16,18 @@ using namespace Utils;
namespace ProjectExplorer {
-FileTransferDirection FileToTransfer::direction() const
-{
- if (m_source.needsDevice() == m_target.needsDevice())
- return FileTransferDirection::Invalid;
- return m_source.needsDevice() ? FileTransferDirection::Download : FileTransferDirection::Upload;
-}
-
QString FileTransferSetupData::defaultRsyncFlags()
{
return "-av";
}
-static FileTransferDirection transferDirection(const FilesToTransfer &files)
-{
- if (files.isEmpty())
- return FileTransferDirection::Invalid;
-
- const FileTransferDirection direction = files.first().direction();
- for (const FileToTransfer &file : files) {
- if (file.direction() != direction)
- return FileTransferDirection::Invalid;
- }
- return direction;
-}
-
-static const FilePath &remoteFile(FileTransferDirection direction, const FileToTransfer &file)
-{
- return direction == FileTransferDirection::Upload ? file.m_target : file.m_source;
-}
-
-static IDeviceConstPtr matchedDevice(FileTransferDirection direction, const FilesToTransfer &files)
+static IDeviceConstPtr matchedDevice(const FilesToTransfer &files)
{
if (files.isEmpty())
return {};
- const FilePath &filePath = remoteFile(direction, files.first());
+ const FilePath filePath = files.first().m_target;
for (const FileToTransfer &file : files) {
- if (!filePath.isSameDevice(remoteFile(direction, file)))
+ if (!filePath.isSameDevice(file.m_target))
return {};
}
return DeviceManager::deviceForPath(filePath);
@@ -102,15 +77,11 @@ void FileTransferPrivate::start()
if (m_setup.m_files.isEmpty())
return startFailed(Tr::tr("No files to transfer."));
- const FileTransferDirection direction = transferDirection(m_setup.m_files);
-
- IDeviceConstPtr device;
- if (direction != FileTransferDirection::Invalid)
- device = matchedDevice(direction, m_setup.m_files);
+ IDeviceConstPtr device = matchedDevice(m_setup.m_files);
if (!device) {
// Fall back to generic copy.
- const FilePath &filePath = m_setup.m_files.first().m_target;
+ const FilePath filePath = m_setup.m_files.first().m_target;
device = DeviceManager::deviceForPath(filePath);
m_setup.m_method = FileTransferMethod::GenericCopy;
}
@@ -222,7 +193,7 @@ QString FileTransfer::transferMethodName(FileTransferMethod method)
return {};
}
-FileTransferAdapter::FileTransferAdapter()
+FileTransferTaskAdapter::FileTransferTaskAdapter()
{
connect(task(), &FileTransfer::done, this, [this](const ProcessResultData &result) {
emit done(result.m_exitStatus == QProcess::NormalExit
diff --git a/src/plugins/projectexplorer/devicesupport/filetransfer.h b/src/plugins/projectexplorer/devicesupport/filetransfer.h
index dcc04f05c0..f73a374168 100644
--- a/src/plugins/projectexplorer/devicesupport/filetransfer.h
+++ b/src/plugins/projectexplorer/devicesupport/filetransfer.h
@@ -7,7 +7,7 @@
#include "filetransferinterface.h"
#include "idevicefwd.h"
-#include <utils/tasktree.h>
+#include <solutions/tasking/tasktree.h>
namespace Utils { class ProcessResultData; }
@@ -46,14 +46,14 @@ private:
FileTransferPrivate *d;
};
-class PROJECTEXPLORER_EXPORT FileTransferAdapter : public Utils::Tasking::TaskAdapter<FileTransfer>
+class PROJECTEXPLORER_EXPORT FileTransferTaskAdapter : public Tasking::TaskAdapter<FileTransfer>
{
public:
- FileTransferAdapter();
+ FileTransferTaskAdapter();
void start() override { task()->start(); }
};
-class PROJECTEXPLORER_EXPORT FileTransferTestAdapter : public FileTransferAdapter
+class PROJECTEXPLORER_EXPORT FileTransferTestTaskAdapter : public FileTransferTaskAdapter
{
public:
void start() final { task()->test(); }
@@ -61,5 +61,5 @@ public:
} // namespace ProjectExplorer
-QTC_DECLARE_CUSTOM_TASK(Transfer, ProjectExplorer::FileTransferAdapter);
-QTC_DECLARE_CUSTOM_TASK(TransferTest, ProjectExplorer::FileTransferTestAdapter);
+TASKING_DECLARE_TASK(FileTransferTask, ProjectExplorer::FileTransferTaskAdapter);
+TASKING_DECLARE_TASK(FileTransferTestTask, ProjectExplorer::FileTransferTestTaskAdapter);
diff --git a/src/plugins/projectexplorer/devicesupport/filetransferinterface.h b/src/plugins/projectexplorer/devicesupport/filetransferinterface.h
index 2907f9c257..ce4e662db4 100644
--- a/src/plugins/projectexplorer/devicesupport/filetransferinterface.h
+++ b/src/plugins/projectexplorer/devicesupport/filetransferinterface.h
@@ -11,12 +11,6 @@ namespace Utils { class ProcessResultData; }
namespace ProjectExplorer {
-enum class FileTransferDirection {
- Invalid,
- Upload,
- Download
-};
-
enum class FileTransferMethod {
Sftp,
Rsync,
@@ -29,8 +23,6 @@ class PROJECTEXPLORER_EXPORT FileToTransfer
public:
Utils::FilePath m_source;
Utils::FilePath m_target;
-
- FileTransferDirection direction() const;
};
using FilesToTransfer = QList<FileToTransfer>;
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp
index b884237b3b..50f552444b 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp
@@ -15,6 +15,7 @@
#include <coreplugin/icore.h>
+#include <utils/commandline.h>
#include <utils/devicefileaccess.h>
#include <utils/displayname.h>
#include <utils/icon.h>
@@ -92,6 +93,7 @@ static Id newId()
const char DisplayNameKey[] = "Name";
const char TypeKey[] = "OsType";
+const char ClientOsTypeKey[] = "ClientOsType";
const char IdKey[] = "InternalId";
const char OriginKey[] = "Origin";
const char MachineTypeKey[] = "Type";
@@ -369,6 +371,27 @@ const QList<IDevice::DeviceAction> IDevice::deviceActions() const
return d->deviceActions;
}
+PortsGatheringMethod IDevice::portsGatheringMethod() const
+{
+ return {[this](QAbstractSocket::NetworkLayerProtocol protocol) -> CommandLine {
+ // We might encounter the situation that protocol is given IPv6
+ // but the consumer of the free port information decides to open
+ // an IPv4(only) port. As a result the next IPv6 scan will
+ // report the port again as open (in IPv6 namespace), while the
+ // same port in IPv4 namespace might still be blocked, and
+ // re-use of this port fails.
+ // GDBserver behaves exactly like this.
+
+ Q_UNUSED(protocol)
+
+ if (filePath("/proc/net").isReadableDir())
+ return {filePath("/bin/sh"), {"-c", "cat /proc/net/tcp*"}};
+
+ return {filePath("netstat"), {"-a", "-n"}};
+ },
+ &Port::parseFromCommandOutput};
+};
+
DeviceProcessList *IDevice::createProcessListModel(QObject *parent) const
{
Q_UNUSED(parent)
@@ -425,6 +448,8 @@ void IDevice::fromMap(const QVariantMap &map)
d->type = typeFromMap(map);
d->displayName.fromMap(map, DisplayNameKey);
d->id = Id::fromSetting(map.value(QLatin1String(IdKey)));
+ d->osType = osTypeFromString(
+ map.value(QLatin1String(ClientOsTypeKey), osTypeToString(OsTypeLinux)).toString());
if (!d->id.isValid())
d->id = newId();
d->origin = static_cast<Origin>(map.value(QLatin1String(OriginKey), ManuallyAdded).toInt());
@@ -471,6 +496,7 @@ QVariantMap IDevice::toMap() const
QVariantMap map;
d->displayName.toMap(map, DisplayNameKey);
map.insert(QLatin1String(TypeKey), d->type.toString());
+ map.insert(QLatin1String(ClientOsTypeKey), osTypeToString(d->osType));
map.insert(QLatin1String(IdKey), d->id.toSetting());
map.insert(QLatin1String(OriginKey), d->origin);
@@ -503,9 +529,6 @@ IDevice::Ptr IDevice::clone() const
device->d->deviceState = d->deviceState;
device->d->deviceActions = d->deviceActions;
device->d->deviceIcons = d->deviceIcons;
- // Os type is only set in the constructor, always to the same value.
- // But make sure we notice if that changes in the future (which it shouldn't).
- QTC_CHECK(device->d->osType == d->osType);
device->d->osType = d->osType;
device->fromMap(toMap());
return device;
@@ -578,16 +601,6 @@ void IDevice::setDebugServerPath(const FilePath &path)
d->debugServerPath = path;
}
-FilePath IDevice::debugDumperPath() const
-{
- return d->debugDumperPath;
-}
-
-void IDevice::setDebugDumperPath(const FilePath &path)
-{
- d->debugDumperPath = path;
-}
-
FilePath IDevice::qmlRunCommand() const
{
return d->qmlRunCommand;
@@ -682,12 +695,12 @@ void DeviceProcessKiller::start()
m_signalOperation->killProcess(m_processPath.path());
}
-KillerAdapter::KillerAdapter()
+DeviceProcessKillerTaskAdapter::DeviceProcessKillerTaskAdapter()
{
- connect(task(), &DeviceProcessKiller::done, this, &KillerAdapter::done);
+ connect(task(), &DeviceProcessKiller::done, this, &TaskInterface::done);
}
-void KillerAdapter::start()
+void DeviceProcessKillerTaskAdapter::start()
{
task()->start();
}
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h
index 6323b8589b..e28f88aaf4 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.h
+++ b/src/plugins/projectexplorer/devicesupport/idevice.h
@@ -6,11 +6,12 @@
#include "../projectexplorer_export.h"
#include "idevicefwd.h"
+#include <solutions/tasking/tasktree.h>
+
#include <utils/id.h>
#include <utils/expected.h>
#include <utils/filepath.h>
#include <utils/hostosinfo.h>
-#include <utils/tasktree.h>
#include <QAbstractSocket>
#include <QCoreApplication>
@@ -35,7 +36,7 @@ class Icon;
class PortList;
class Port;
class ProcessInterface;
-class QtcProcess;
+class Process;
} // Utils
namespace ProjectExplorer {
@@ -139,10 +140,7 @@ public:
void addDeviceAction(const DeviceAction &deviceAction);
const QList<DeviceAction> deviceActions() const;
- // Devices that can auto detect ports need not return a ports gathering method. Such devices can
- // obtain a free port on demand. eg: Desktop device.
- virtual bool canAutoDetectPorts() const { return false; }
- virtual PortsGatheringMethod portsGatheringMethod() const { return {}; }
+ virtual PortsGatheringMethod portsGatheringMethod() const;
virtual bool canCreateProcessModel() const { return false; }
virtual DeviceProcessList *createProcessListModel(QObject *parent = nullptr) const;
virtual bool hasDeviceTester() const { return false; }
@@ -179,9 +177,6 @@ public:
Utils::FilePath debugServerPath() const;
void setDebugServerPath(const Utils::FilePath &path);
- Utils::FilePath debugDumperPath() const;
- void setDebugDumperPath(const Utils::FilePath &path);
-
Utils::FilePath qmlRunCommand() const;
void setQmlRunCommand(const Utils::FilePath &path);
@@ -221,6 +216,8 @@ public:
virtual bool prepareForBuild(const Target *target);
virtual std::optional<Utils::FilePath> clangdExecutable() const;
+ virtual void checkOsType() {}
+
protected:
IDevice();
@@ -280,13 +277,14 @@ private:
QString m_errorString;
};
-class PROJECTEXPLORER_EXPORT KillerAdapter : public Utils::Tasking::TaskAdapter<DeviceProcessKiller>
+class PROJECTEXPLORER_EXPORT DeviceProcessKillerTaskAdapter
+ : public Tasking::TaskAdapter<DeviceProcessKiller>
{
public:
- KillerAdapter();
+ DeviceProcessKillerTaskAdapter();
void start() final;
};
} // namespace ProjectExplorer
-QTC_DECLARE_CUSTOM_TASK(Killer, ProjectExplorer::KillerAdapter);
+TASKING_DECLARE_TASK(DeviceProcessKillerTask, ProjectExplorer::DeviceProcessKillerTaskAdapter);
diff --git a/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp b/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp
index c33bc125bb..b517844570 100644
--- a/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp
@@ -63,12 +63,25 @@ bool IDeviceFactory::canCreate() const
IDevice::Ptr IDeviceFactory::create() const
{
- return m_creator ? m_creator() : IDevice::Ptr();
+ if (!m_creator)
+ return {};
+
+ IDevice::Ptr device = m_creator();
+ if (!device) // e.g. Cancel used on the dialog to create a device
+ return {};
+ device->setDefaultDisplayName(displayName());
+ return device;
}
IDevice::Ptr IDeviceFactory::construct() const
{
- return m_constructor ? m_constructor() : IDevice::Ptr();
+ if (!m_constructor)
+ return {};
+
+ IDevice::Ptr device = m_constructor();
+ QTC_ASSERT(device, return {});
+ device->setDefaultDisplayName(displayName());
+ return device;
}
static QList<IDeviceFactory *> g_deviceFactories;
@@ -105,6 +118,16 @@ void IDeviceFactory::setCreator(const std::function<IDevice::Ptr ()> &creator)
m_creator = creator;
}
+void IDeviceFactory::setQuickCreationAllowed(bool on)
+{
+ m_quickCreationAllowed = on;
+}
+
+bool IDeviceFactory::quickCreationAllowed() const
+{
+ return m_quickCreationAllowed;
+}
+
void IDeviceFactory::setConstructionFunction(const std::function<IDevice::Ptr ()> &constructor)
{
m_constructor = constructor;
diff --git a/src/plugins/projectexplorer/devicesupport/idevicefactory.h b/src/plugins/projectexplorer/devicesupport/idevicefactory.h
index 87a54244ad..665059f5b2 100644
--- a/src/plugins/projectexplorer/devicesupport/idevicefactory.h
+++ b/src/plugins/projectexplorer/devicesupport/idevicefactory.h
@@ -26,6 +26,7 @@ public:
bool canCreate() const;
IDevicePtr construct() const;
IDevicePtr create() const;
+ bool quickCreationAllowed() const;
virtual bool canRestore(const QVariantMap &) const { return true; }
@@ -41,6 +42,7 @@ protected:
void setCombinedIcon(const Utils::FilePath &smallIcon, const Utils::FilePath &largeIcon);
void setConstructionFunction(const std::function<IDevicePtr ()> &constructor);
void setCreator(const std::function<IDevicePtr()> &creator);
+ void setQuickCreationAllowed(bool on);
private:
std::function<IDevicePtr()> m_creator;
@@ -48,6 +50,7 @@ private:
QString m_displayName;
QIcon m_icon;
std::function<IDevicePtr()> m_constructor;
+ bool m_quickCreationAllowed = false;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
deleted file mode 100644
index c6fd49012f..0000000000
--- a/src/plugins/projectexplorer/devicesupport/localprocesslist.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "localprocesslist.h"
-
-#include <projectexplorer/devicesupport/idevice.h>
-#include <utils/processinfo.h>
-
-#include <QTimer>
-
-#if defined(Q_OS_UNIX)
-#include <unistd.h>
-#elif defined(Q_OS_WIN)
-#include <windows.h>
-#endif
-
-using namespace Utils;
-
-namespace ProjectExplorer {
-namespace Internal {
-
-LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent)
- : DeviceProcessList(device, parent)
-{
-#if defined(Q_OS_UNIX)
- setOwnPid(getpid());
-#elif defined(Q_OS_WIN)
- setOwnPid(GetCurrentProcessId());
-#endif
-}
-
-void LocalProcessList::doKillProcess(const ProcessInfo &processInfo)
-{
- DeviceProcessSignalOperation::Ptr signalOperation = device()->signalOperation();
- connect(signalOperation.data(), &DeviceProcessSignalOperation::finished,
- this, &LocalProcessList::reportDelayedKillStatus);
- signalOperation->killProcess(processInfo.processId);
-}
-
-void LocalProcessList::handleUpdate()
-{
- reportProcessListUpdated(ProcessInfo::processInfoList());
-}
-
-void LocalProcessList::doUpdate()
-{
- QTimer::singleShot(0, this, &LocalProcessList::handleUpdate);
-}
-
-void LocalProcessList::reportDelayedKillStatus(const QString &errorMessage)
-{
- if (errorMessage.isEmpty())
- reportProcessKilled();
- else
- reportError(errorMessage);
-}
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/processlist.cpp b/src/plugins/projectexplorer/devicesupport/processlist.cpp
new file mode 100644
index 0000000000..11e0932832
--- /dev/null
+++ b/src/plugins/projectexplorer/devicesupport/processlist.cpp
@@ -0,0 +1,61 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "processlist.h"
+
+#include <projectexplorer/devicesupport/idevice.h>
+#include <utils/processinfo.h>
+
+#include <QTimer>
+
+#if defined(Q_OS_UNIX)
+#include <unistd.h>
+#elif defined(Q_OS_WIN)
+#include <windows.h>
+#endif
+
+using namespace Utils;
+
+namespace ProjectExplorer {
+
+ProcessList::ProcessList(const IDevice::ConstPtr &device, QObject *parent)
+ : DeviceProcessList(device, parent)
+{
+#if defined(Q_OS_UNIX)
+ setOwnPid(getpid());
+#elif defined(Q_OS_WIN)
+ setOwnPid(GetCurrentProcessId());
+#endif
+}
+
+void ProcessList::doKillProcess(const ProcessInfo &processInfo)
+{
+ m_signalOperation = device()->signalOperation();
+ connect(m_signalOperation.data(),
+ &DeviceProcessSignalOperation::finished,
+ this,
+ &ProcessList::reportDelayedKillStatus);
+ m_signalOperation->killProcess(processInfo.processId);
+}
+
+void ProcessList::handleUpdate()
+{
+ reportProcessListUpdated(ProcessInfo::processInfoList(DeviceProcessList::device()->rootPath()));
+}
+
+void ProcessList::doUpdate()
+{
+ QTimer::singleShot(0, this, &ProcessList::handleUpdate);
+}
+
+void ProcessList::reportDelayedKillStatus(const QString &errorMessage)
+{
+ if (errorMessage.isEmpty())
+ reportProcessKilled();
+ else
+ reportError(errorMessage);
+
+ m_signalOperation.reset();
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/localprocesslist.h b/src/plugins/projectexplorer/devicesupport/processlist.h
index e3445f47b2..caebaf22f9 100644
--- a/src/plugins/projectexplorer/devicesupport/localprocesslist.h
+++ b/src/plugins/projectexplorer/devicesupport/processlist.h
@@ -4,16 +4,16 @@
#pragma once
#include "deviceprocesslist.h"
+#include "idevice.h"
namespace ProjectExplorer {
-namespace Internal {
-class LocalProcessList : public DeviceProcessList
+class PROJECTEXPLORER_EXPORT ProcessList : public DeviceProcessList
{
Q_OBJECT
public:
- explicit LocalProcessList(const IDeviceConstPtr &device, QObject *parent = nullptr);
+ explicit ProcessList(const IDeviceConstPtr &device, QObject *parent = nullptr);
private:
void doUpdate() override;
@@ -22,7 +22,9 @@ private:
private:
void handleUpdate();
void reportDelayedKillStatus(const QString &errorMessage);
+
+private:
+ DeviceProcessSignalOperation::Ptr m_signalOperation;
};
-} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
deleted file mode 100644
index d64cde6e3e..0000000000
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "sshdeviceprocesslist.h"
-
-#include "idevice.h"
-#include "../projectexplorertr.h"
-
-#include <utils/processinfo.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-#include <utils/stringutils.h>
-
-using namespace Utils;
-
-namespace ProjectExplorer {
-
-class SshDeviceProcessListPrivate
-{
-public:
- QtcProcess m_process;
- DeviceProcessSignalOperation::Ptr m_signalOperation;
-};
-
-SshDeviceProcessList::SshDeviceProcessList(const IDevice::ConstPtr &device, QObject *parent) :
- DeviceProcessList(device, parent), d(std::make_unique<SshDeviceProcessListPrivate>())
-{
- connect(&d->m_process, &QtcProcess::done, this, &SshDeviceProcessList::handleProcessDone);
-}
-
-SshDeviceProcessList::~SshDeviceProcessList() = default;
-
-void SshDeviceProcessList::doUpdate()
-{
- d->m_process.close();
- d->m_process.setCommand({device()->filePath("/bin/sh"), {"-c", listProcessesCommandLine()}});
- d->m_process.start();
-}
-
-void SshDeviceProcessList::doKillProcess(const ProcessInfo &process)
-{
- d->m_signalOperation = device()->signalOperation();
- QTC_ASSERT(d->m_signalOperation, return);
- connect(d->m_signalOperation.data(), &DeviceProcessSignalOperation::finished,
- this, &SshDeviceProcessList::handleKillProcessFinished);
- d->m_signalOperation->killProcess(process.processId);
-}
-
-void SshDeviceProcessList::handleProcessDone()
-{
- if (d->m_process.result() == ProcessResult::FinishedWithSuccess) {
- reportProcessListUpdated(buildProcessList(d->m_process.cleanedStdOut()));
- } else {
- const QString errorString = d->m_process.exitStatus() == QProcess::NormalExit
- ? Tr::tr("Process listing command failed with exit code %1.").arg(d->m_process.exitCode())
- : d->m_process.errorString();
- const QString stdErr = d->m_process.cleanedStdErr();
- const QString outputString
- = stdErr.isEmpty() ? stdErr : Tr::tr("Remote stderr was: %1").arg(stdErr);
- reportError(Utils::joinStrings({errorString, outputString}, '\n'));
- }
- setFinished();
-}
-
-void SshDeviceProcessList::handleKillProcessFinished(const QString &errorString)
-{
- if (errorString.isEmpty())
- reportProcessKilled();
- else
- reportError(Tr::tr("Error: Kill process failed: %1").arg(errorString));
- setFinished();
-}
-
-void SshDeviceProcessList::setFinished()
-{
- d->m_process.close();
- if (d->m_signalOperation) {
- d->m_signalOperation->disconnect(this);
- d->m_signalOperation.clear();
- }
-}
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h
deleted file mode 100644
index fd560f5375..0000000000
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "deviceprocesslist.h"
-
-#include <memory>
-
-namespace ProjectExplorer {
-
-class SshDeviceProcessListPrivate;
-
-class PROJECTEXPLORER_EXPORT SshDeviceProcessList : public DeviceProcessList
-{
- Q_OBJECT
-public:
- explicit SshDeviceProcessList(const IDeviceConstPtr &device, QObject *parent = nullptr);
- ~SshDeviceProcessList() override;
-
-private:
- void handleProcessDone();
- void handleKillProcessFinished(const QString &errorString);
-
- virtual QString listProcessesCommandLine() const = 0;
- virtual QList<Utils::ProcessInfo> buildProcessList(const QString &listProcessesReply) const = 0;
-
- void doUpdate() override;
- void doKillProcess(const Utils::ProcessInfo &process) override;
-
- void setFinished();
-
- const std::unique_ptr<SshDeviceProcessListPrivate> d;
-};
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/devicesupport/sshparameters.cpp b/src/plugins/projectexplorer/devicesupport/sshparameters.cpp
index 3cc6364a67..744e350eae 100644
--- a/src/plugins/projectexplorer/devicesupport/sshparameters.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshparameters.cpp
@@ -8,8 +8,8 @@
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <QDebug>
@@ -19,9 +19,17 @@ using namespace Utils;
namespace ProjectExplorer {
-SshParameters::SshParameters()
+SshParameters::SshParameters() = default;
+
+QString SshParameters::userAtHost() const
{
- url.setPort(0);
+ QString res;
+ if (!m_userName.isEmpty())
+ res = m_userName + '@';
+ res += m_host;
+ if (m_port != 22)
+ res += QString(":%1").arg(m_port);
+ return res;
}
QStringList SshParameters::connectionOptions(const FilePath &binary) const
@@ -61,7 +69,7 @@ QStringList SshParameters::connectionOptions(const FilePath &binary) const
return args;
}
-bool SshParameters::setupSshEnvironment(QtcProcess *process)
+bool SshParameters::setupSshEnvironment(Process *process)
{
Environment env = process->controlEnvironment();
if (!env.hasChanges())
@@ -81,10 +89,11 @@ bool SshParameters::setupSshEnvironment(QtcProcess *process)
return hasDisplay;
}
-
-static inline bool equals(const SshParameters &p1, const SshParameters &p2)
+bool operator==(const SshParameters &p1, const SshParameters &p2)
{
- return p1.url == p2.url
+ return p1.m_host == p2.m_host
+ && p1.m_port == p2.m_port
+ && p1.m_userName == p2.m_userName
&& p1.authenticationType == p2.authenticationType
&& p1.privateKeyFile == p2.privateKeyFile
&& p1.hostKeyCheckingMode == p2.hostKeyCheckingMode
@@ -92,16 +101,6 @@ static inline bool equals(const SshParameters &p1, const SshParameters &p2)
&& p1.timeout == p2.timeout;
}
-bool operator==(const SshParameters &p1, const SshParameters &p2)
-{
- return equals(p1, p2);
-}
-
-bool operator!=(const SshParameters &p1, const SshParameters &p2)
-{
- return !equals(p1, p2);
-}
-
#ifdef WITH_TESTS
namespace SshTest {
const QString getHostFromEnvironment()
diff --git a/src/plugins/projectexplorer/devicesupport/sshparameters.h b/src/plugins/projectexplorer/devicesupport/sshparameters.h
index 00b63e3aac..3ee483d5f3 100644
--- a/src/plugins/projectexplorer/devicesupport/sshparameters.h
+++ b/src/plugins/projectexplorer/devicesupport/sshparameters.h
@@ -7,9 +7,7 @@
#include <utils/filepath.h>
-#include <QUrl>
-
-namespace Utils { class QtcProcess; }
+namespace Utils { class Process; }
namespace ProjectExplorer {
@@ -29,28 +27,34 @@ public:
SshParameters();
- QString host() const { return url.host(); }
- quint16 port() const { return url.port(); }
- QString userName() const { return url.userName(); }
- QString userAtHost() const { return userName().isEmpty() ? host() : userName() + '@' + host(); }
- void setHost(const QString &host) { url.setHost(host); }
- void setPort(int port) { url.setPort(port); }
- void setUserName(const QString &name) { url.setUserName(name); }
+ QString host() const { return m_host; }
+ quint16 port() const { return m_port; }
+ QString userName() const { return m_userName; }
+
+ QString userAtHost() const;
+
+ void setHost(const QString &host) { m_host = host; }
+ void setPort(int port) { m_port = port; }
+ void setUserName(const QString &name) { m_userName = name; }
QStringList connectionOptions(const Utils::FilePath &binary) const;
- QUrl url;
Utils::FilePath privateKeyFile;
QString x11DisplayName;
int timeout = 0; // In seconds.
AuthenticationType authenticationType = AuthenticationTypeAll;
SshHostKeyCheckingMode hostKeyCheckingMode = SshHostKeyCheckingAllowNoMatch;
- static bool setupSshEnvironment(Utils::QtcProcess *process);
-};
+ static bool setupSshEnvironment(Utils::Process *process);
+
+ friend PROJECTEXPLORER_EXPORT bool operator==(const SshParameters &p1, const SshParameters &p2);
+ friend bool operator!=(const SshParameters &p1, const SshParameters &p2) { return !(p1 == p2); }
-PROJECTEXPLORER_EXPORT bool operator==(const SshParameters &p1, const SshParameters &p2);
-PROJECTEXPLORER_EXPORT bool operator!=(const SshParameters &p1, const SshParameters &p2);
+private:
+ QString m_host;
+ quint16 m_port = 22;
+ QString m_userName;
+};
#ifdef WITH_TESTS
namespace SshTest {
diff --git a/src/plugins/projectexplorer/editorconfiguration.cpp b/src/plugins/projectexplorer/editorconfiguration.cpp
index fc3933d734..ff99bc25e8 100644
--- a/src/plugins/projectexplorer/editorconfiguration.cpp
+++ b/src/plugins/projectexplorer/editorconfiguration.cpp
@@ -5,7 +5,7 @@
#include "project.h"
#include "projectexplorertr.h"
-#include "session.h"
+#include "projectmanager.h"
#include <utils/algorithm.h>
@@ -88,7 +88,7 @@ EditorConfiguration::EditorConfiguration() : d(std::make_unique<EditorConfigurat
// if setCurrentDelegate is 0 values are read from *this prefs
d->m_defaultCodeStyle->setCurrentDelegate(TextEditorSettings::codeStyle());
- connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject,
+ connect(ProjectManager::instance(), &ProjectManager::aboutToRemoveProject,
this, &EditorConfiguration::slotAboutToRemoveProject);
}
@@ -263,7 +263,7 @@ void EditorConfiguration::setUseGlobalSettings(bool use)
const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForOpenedDocuments();
for (Core::IEditor *editor : editors) {
if (auto widget = TextEditorWidget::fromEditor(editor)) {
- Project *project = SessionManager::projectForFile(editor->document()->filePath());
+ Project *project = ProjectManager::projectForFile(editor->document()->filePath());
if (project && project->editorConfiguration() == this)
switchSettings(widget);
}
@@ -399,7 +399,7 @@ TabSettings actualTabSettings(const Utils::FilePath &file,
{
if (baseTextdocument)
return baseTextdocument->tabSettings();
- if (Project *project = SessionManager::projectForFile(file))
+ if (Project *project = ProjectManager::projectForFile(file))
return project->editorConfiguration()->codeStyle()->tabSettings();
return TextEditorSettings::codeStyle()->tabSettings();
}
diff --git a/src/plugins/projectexplorer/editorsettingspropertiespage.cpp b/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
index 52450b2bc8..e0c2b93bb2 100644
--- a/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/editorsettingspropertiespage.cpp
@@ -48,7 +48,7 @@ EditorSettingsWidget::EditorSettingsWidget(Project *project) : m_project(project
m_behaviorSettings = new TextEditor::BehaviorSettingsWidget(this);
- using namespace Utils::Layouting;
+ using namespace Layouting;
Row {
m_showWrapColumn,
@@ -63,7 +63,8 @@ EditorSettingsWidget::EditorSettingsWidget(Project *project) : m_project(project
m_displaySettings,
m_behaviorSettings,
st,
- }.attachTo(this, WithoutMargins);
+ noMargin
+ }.attachTo(this);
const EditorConfiguration *config = m_project->editorConfiguration();
settingsToUi(config);
diff --git a/src/plugins/projectexplorer/environmentaspect.cpp b/src/plugins/projectexplorer/environmentaspect.cpp
index 66a2b3bc99..09bfeb9c80 100644
--- a/src/plugins/projectexplorer/environmentaspect.cpp
+++ b/src/plugins/projectexplorer/environmentaspect.cpp
@@ -3,8 +3,11 @@
#include "environmentaspect.h"
+#include "buildconfiguration.h"
#include "environmentaspectwidget.h"
+#include "kit.h"
#include "projectexplorertr.h"
+#include "target.h"
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -12,6 +15,7 @@
using namespace Utils;
namespace ProjectExplorer {
+const char PRINT_ON_RUN_KEY[] = "PE.EnvironmentAspect.PrintOnRun";
// --------------------------------------------------------------------
// EnvironmentAspect:
@@ -101,16 +105,39 @@ int EnvironmentAspect::addPreferredBaseEnvironment(const QString &displayName,
return index;
}
+void EnvironmentAspect::setSupportForBuildEnvironment(Target *target)
+{
+ setIsLocal(true);
+ addSupportedBaseEnvironment(Tr::tr("Clean Environment"), {});
+
+ addSupportedBaseEnvironment(Tr::tr("System Environment"), [] {
+ return Environment::systemEnvironment();
+ });
+ addPreferredBaseEnvironment(Tr::tr("Build Environment"), [target] {
+ if (BuildConfiguration *bc = target->activeBuildConfiguration())
+ return bc->environment();
+ // Fallback for targets without buildconfigurations:
+ return target->kit()->buildEnvironment();
+ });
+
+ connect(target, &Target::activeBuildConfigurationChanged,
+ this, &EnvironmentAspect::environmentChanged);
+ connect(target, &Target::buildEnvironmentChanged,
+ this, &EnvironmentAspect::environmentChanged);
+}
+
void EnvironmentAspect::fromMap(const QVariantMap &map)
{
m_base = map.value(QLatin1String(BASE_KEY), -1).toInt();
m_userChanges = Utils::EnvironmentItem::fromStringList(map.value(QLatin1String(CHANGES_KEY)).toStringList());
+ m_printOnRun = map.value(PRINT_ON_RUN_KEY).toBool();
}
void EnvironmentAspect::toMap(QVariantMap &data) const
{
data.insert(QLatin1String(BASE_KEY), m_base);
data.insert(QLatin1String(CHANGES_KEY), Utils::EnvironmentItem::toStringList(m_userChanges));
+ data.insert(PRINT_ON_RUN_KEY, m_printOnRun);
}
QString EnvironmentAspect::currentDisplayName() const
diff --git a/src/plugins/projectexplorer/environmentaspect.h b/src/plugins/projectexplorer/environmentaspect.h
index 5b1d0d1c41..97ce26f017 100644
--- a/src/plugins/projectexplorer/environmentaspect.h
+++ b/src/plugins/projectexplorer/environmentaspect.h
@@ -39,6 +39,8 @@ public:
int addPreferredBaseEnvironment(const QString &displayName,
const std::function<Utils::Environment()> &getter);
+ void setSupportForBuildEnvironment(Target *target);
+
QString currentDisplayName() const;
const QStringList displayNames() const;
@@ -48,6 +50,10 @@ public:
bool isLocal() const { return m_isLocal; }
+ bool isPrintOnRunAllowed() const { return m_allowPrintOnRun; }
+ bool isPrintOnRunEnabled() const { return m_printOnRun; }
+ void setPrintOnRun(bool enabled) { m_printOnRun = enabled; }
+
struct Data : BaseAspect::Data
{
Utils::Environment environment;
@@ -66,6 +72,7 @@ protected:
void toMap(QVariantMap &map) const override;
void setIsLocal(bool local) { m_isLocal = local; }
+ void setAllowPrintOnRun(bool allow) { m_allowPrintOnRun = allow; }
static constexpr char BASE_KEY[] = "PE.EnvironmentAspect.Base";
static constexpr char CHANGES_KEY[] = "PE.EnvironmentAspect.Changes";
@@ -84,6 +91,8 @@ private:
QList<BaseEnvironment> m_baseEnvironments;
int m_base = -1;
bool m_isLocal = false;
+ bool m_allowPrintOnRun = true;
+ bool m_printOnRun = false;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/environmentaspectwidget.cpp b/src/plugins/projectexplorer/environmentaspectwidget.cpp
index 18babfcf61..34e48af42c 100644
--- a/src/plugins/projectexplorer/environmentaspectwidget.cpp
+++ b/src/plugins/projectexplorer/environmentaspectwidget.cpp
@@ -9,6 +9,7 @@
#include <utils/environment.h>
#include <utils/qtcassert.h>
+#include <QCheckBox>
#include <QComboBox>
#include <QHBoxLayout>
#include <QLabel>
@@ -63,6 +64,14 @@ EnvironmentAspectWidget::EnvironmentAspectWidget(EnvironmentAspect *aspect)
m_environmentWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
topLayout->addWidget(m_environmentWidget);
+ if (m_aspect->isPrintOnRunAllowed()) {
+ const auto printOnRunCheckBox = new QCheckBox(Tr::tr("Show in output pane when running"));
+ printOnRunCheckBox->setChecked(m_aspect->isPrintOnRunEnabled());
+ connect(printOnRunCheckBox, &QCheckBox::toggled,
+ m_aspect, &EnvironmentAspect::setPrintOnRun);
+ topLayout->addWidget(printOnRunCheckBox);
+ }
+
connect(m_environmentWidget, &EnvironmentWidget::userChangesChanged,
this, &EnvironmentAspectWidget::userChangesEdited);
diff --git a/src/plugins/projectexplorer/extraabi.cpp b/src/plugins/projectexplorer/extraabi.cpp
index 24a2861103..19f970b11a 100644
--- a/src/plugins/projectexplorer/extraabi.cpp
+++ b/src/plugins/projectexplorer/extraabi.cpp
@@ -4,7 +4,6 @@
#include "extraabi.h"
#include "abi.h"
-#include "projectexplorertr.h"
#include <coreplugin/icore.h>
@@ -36,17 +35,15 @@ public:
class AbiFlavorAccessor : public UpgradingSettingsAccessor
{
public:
- AbiFlavorAccessor();
+ AbiFlavorAccessor()
+ {
+ setDocType("QtCreatorExtraAbi");
+ setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME);
+ setBaseFilePath(Core::ICore::installerResourcePath("abi.xml"));
+ addVersionUpgrader(std::make_unique<AbiFlavorUpgraderV0>());
+ }
};
-AbiFlavorAccessor::AbiFlavorAccessor() :
- UpgradingSettingsAccessor("QtCreatorExtraAbi", Tr::tr("ABI"),
- Core::Constants::IDE_DISPLAY_NAME)
-{
- setBaseFilePath(Core::ICore::installerResourcePath("abi.xml"));
-
- addVersionUpgrader(std::make_unique<AbiFlavorUpgraderV0>());
-}
// --------------------------------------------------------------------
// ExtraAbi:
diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp
index ab72d3608f..67bb4a63fc 100644
--- a/src/plugins/projectexplorer/extracompiler.cpp
+++ b/src/plugins/projectexplorer/extracompiler.cpp
@@ -5,23 +5,26 @@
#include "buildmanager.h"
#include "kitinformation.h"
-#include "session.h"
+#include "projectmanager.h"
#include "target.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/idocument.h>
-#include <utils/asynctask.h>
+#include <extensionsystem/pluginmanager.h>
+
+#include <utils/async.h>
#include <utils/expected.h>
#include <utils/guard.h>
-#include <utils/qtcprocess.h>
+#include <utils/process.h>
#include <QDateTime>
-#include <QFutureInterface>
#include <QLoggingCategory>
#include <QThreadPool>
#include <QTimer>
+using namespace Core;
+using namespace Tasking;
using namespace Utils;
namespace ProjectExplorer {
@@ -37,15 +40,14 @@ public:
FilePath source;
FileNameToContentsHash contents;
QDateTime compileTime;
- Core::IEditor *lastEditor = nullptr;
+ IEditor *lastEditor = nullptr;
QMetaObject::Connection activeBuildConfigConnection;
QMetaObject::Connection activeEnvironmentConnection;
- Utils::Guard lock;
+ Guard lock;
bool dirty = false;
QTimer timer;
- FutureSynchronizer m_futureSynchronizer;
std::unique_ptr<TaskTree> m_taskTree;
};
@@ -63,16 +65,16 @@ ExtraCompiler::ExtraCompiler(const Project *project, const FilePath &source,
connect(BuildManager::instance(), &BuildManager::buildStateChanged,
this, &ExtraCompiler::onTargetsBuilt);
- connect(SessionManager::instance(), &SessionManager::projectRemoved,
+ connect(ProjectManager::instance(), &ProjectManager::projectRemoved,
this, [this](Project *project) {
if (project == d->project)
deleteLater();
});
- Core::EditorManager *editorManager = Core::EditorManager::instance();
- connect(editorManager, &Core::EditorManager::currentEditorChanged,
+ EditorManager *editorManager = EditorManager::instance();
+ connect(editorManager, &EditorManager::currentEditorChanged,
this, &ExtraCompiler::onEditorChanged);
- connect(editorManager, &Core::EditorManager::editorAboutToClose,
+ connect(editorManager, &EditorManager::editorAboutToClose,
this, &ExtraCompiler::onEditorAboutToClose);
// Use existing target files, where possible. Otherwise run the compiler.
@@ -135,7 +137,7 @@ QThreadPool *ExtraCompiler::extraCompilerThreadPool()
return s_extraCompilerThreadPool();
}
-Tasking::TaskItem ExtraCompiler::compileFileItem()
+TaskItem ExtraCompiler::compileFileItem()
{
return taskItemImpl(fromFileProvider());
}
@@ -228,12 +230,12 @@ void ExtraCompiler::onTargetsBuilt(Project *project)
});
}
-void ExtraCompiler::onEditorChanged(Core::IEditor *editor)
+void ExtraCompiler::onEditorChanged(IEditor *editor)
{
// Handle old editor
if (d->lastEditor) {
- Core::IDocument *doc = d->lastEditor->document();
- disconnect(doc, &Core::IDocument::contentsChanged,
+ IDocument *doc = d->lastEditor->document();
+ disconnect(doc, &IDocument::contentsChanged,
this, &ExtraCompiler::setDirty);
if (d->dirty) {
@@ -246,7 +248,7 @@ void ExtraCompiler::onEditorChanged(Core::IEditor *editor)
d->lastEditor = editor;
// Handle new editor
- connect(d->lastEditor->document(), &Core::IDocument::contentsChanged,
+ connect(d->lastEditor->document(), &IDocument::contentsChanged,
this, &ExtraCompiler::setDirty);
} else {
d->lastEditor = nullptr;
@@ -259,15 +261,15 @@ void ExtraCompiler::setDirty()
d->timer.start(1000);
}
-void ExtraCompiler::onEditorAboutToClose(Core::IEditor *editor)
+void ExtraCompiler::onEditorAboutToClose(IEditor *editor)
{
if (d->lastEditor != editor)
return;
// Oh no our editor is going to be closed
// get the content first
- Core::IDocument *doc = d->lastEditor->document();
- disconnect(doc, &Core::IDocument::contentsChanged,
+ IDocument *doc = d->lastEditor->document();
+ disconnect(doc, &IDocument::contentsChanged,
this, &ExtraCompiler::setDirty);
if (d->dirty) {
d->dirty = false;
@@ -278,24 +280,17 @@ void ExtraCompiler::onEditorAboutToClose(Core::IEditor *editor)
Environment ExtraCompiler::buildEnvironment() const
{
- if (Target *target = project()->activeTarget()) {
- if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
- return bc->environment();
- } else {
- EnvironmentItems changes =
- EnvironmentKitAspect::environmentChanges(target->kit());
- Environment env = Environment::systemEnvironment();
- env.modify(changes);
- return env;
- }
- }
+ Target *target = project()->activeTarget();
+ if (!target)
+ return Environment::systemEnvironment();
- return Environment::systemEnvironment();
-}
+ if (BuildConfiguration *bc = target->activeBuildConfiguration())
+ return bc->environment();
-Utils::FutureSynchronizer *ExtraCompiler::futureSynchronizer() const
-{
- return &d->m_futureSynchronizer;
+ const EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(target->kit());
+ Environment env = Environment::systemEnvironment();
+ env.modify(changes);
+ return env;
}
void ExtraCompiler::setContent(const FilePath &file, const QByteArray &contents)
@@ -331,15 +326,16 @@ ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const FilePat
ExtraCompiler(project, source, targets, parent)
{ }
-Tasking::TaskItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &provider)
+TaskItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &provider)
{
- const auto setupTask = [=](AsyncTask<FileNameToContentsHash> &async) {
+ const auto setupTask = [=](Async<FileNameToContentsHash> &async) {
async.setThreadPool(extraCompilerThreadPool());
- async.setAsyncCallData(&ProcessExtraCompiler::runInThread, this, command(),
- workingDirectory(), arguments(), provider, buildEnvironment());
- async.setFutureSynchronizer(futureSynchronizer());
+ // The passed synchronizer has cancelOnWait set to true by default.
+ async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
+ async.setConcurrentCallData(&ProcessExtraCompiler::runInThread, this, command(),
+ workingDirectory(), arguments(), provider, buildEnvironment());
};
- const auto taskDone = [=](const AsyncTask<FileNameToContentsHash> &async) {
+ const auto taskDone = [=](const Async<FileNameToContentsHash> &async) {
if (!async.isResultAvailable())
return;
const FileNameToContentsHash data = async.result();
@@ -349,7 +345,7 @@ Tasking::TaskItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &prov
setContent(it.key(), it.value());
updateCompileTime();
};
- return Tasking::Async<FileNameToContentsHash>(setupTask, taskDone);
+ return AsyncTask<FileNameToContentsHash>(setupTask, taskDone);
}
FilePath ProcessExtraCompiler::workingDirectory() const
@@ -374,7 +370,7 @@ Tasks ProcessExtraCompiler::parseIssues(const QByteArray &stdErr)
return {};
}
-void ProcessExtraCompiler::runInThread(QFutureInterface<FileNameToContentsHash> &futureInterface,
+void ProcessExtraCompiler::runInThread(QPromise<FileNameToContentsHash> &promise,
const FilePath &cmd, const FilePath &workDir,
const QStringList &args, const ContentProvider &provider,
const Environment &env)
@@ -386,7 +382,7 @@ void ProcessExtraCompiler::runInThread(QFutureInterface<FileNameToContentsHash>
if (sourceContents.isNull() || !prepareToRun(sourceContents))
return;
- QtcProcess process;
+ Process process;
process.setEnvironment(env);
if (!workDir.isEmpty())
@@ -397,15 +393,15 @@ void ProcessExtraCompiler::runInThread(QFutureInterface<FileNameToContentsHash>
if (!process.waitForStarted())
return;
- while (!futureInterface.isCanceled()) {
+ while (!promise.isCanceled()) {
if (process.waitForFinished(200))
break;
}
- if (futureInterface.isCanceled())
+ if (promise.isCanceled())
return;
- futureInterface.reportResult(handleProcessFinished(&process));
+ promise.addResult(handleProcessFinished(&process));
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/extracompiler.h b/src/plugins/projectexplorer/extracompiler.h
index 34993f3940..1dbda0e424 100644
--- a/src/plugins/projectexplorer/extracompiler.h
+++ b/src/plugins/projectexplorer/extracompiler.h
@@ -10,7 +10,6 @@
#include <utils/environment.h>
#include <utils/filepath.h>
-#include <utils/tasktree.h>
#include <QByteArray>
#include <QHash>
@@ -21,14 +20,12 @@
QT_BEGIN_NAMESPACE
template <typename T>
-class QFutureInterface;
+class QPromise;
class QThreadPool;
QT_END_NAMESPACE
-namespace Utils {
-class FutureSynchronizer;
-class QtcProcess;
-}
+namespace Tasking { class TaskItem; }
+namespace Utils { class Process; }
namespace ProjectExplorer {
@@ -52,7 +49,7 @@ public:
Utils::FilePaths targets() const;
void forEachTarget(std::function<void(const Utils::FilePath &)> func) const;
- Utils::Tasking::TaskItem compileFileItem();
+ Tasking::TaskItem compileFileItem();
void compileFile();
bool isDirty() const;
void block();
@@ -64,7 +61,6 @@ signals:
protected:
static QThreadPool *extraCompilerThreadPool();
- Utils::FutureSynchronizer *futureSynchronizer() const;
void setContent(const Utils::FilePath &file, const QByteArray &content);
void updateCompileTime();
Utils::Environment buildEnvironment() const;
@@ -79,7 +75,7 @@ private:
void compileContent(const QByteArray &content);
void compileImpl(const ContentProvider &provider);
void compileIfDirty();
- virtual Utils::Tasking::TaskItem taskItemImpl(const ContentProvider &provider) = 0;
+ virtual Tasking::TaskItem taskItemImpl(const ContentProvider &provider) = 0;
const std::unique_ptr<ExtraCompilerPrivate> d;
};
@@ -100,13 +96,13 @@ protected:
virtual bool prepareToRun(const QByteArray &sourceContents);
- virtual FileNameToContentsHash handleProcessFinished(Utils::QtcProcess *process) = 0;
+ virtual FileNameToContentsHash handleProcessFinished(Utils::Process *process) = 0;
virtual Tasks parseIssues(const QByteArray &stdErr);
private:
- Utils::Tasking::TaskItem taskItemImpl(const ContentProvider &provider) final;
- void runInThread(QFutureInterface<FileNameToContentsHash> &futureInterface,
+ Tasking::TaskItem taskItemImpl(const ContentProvider &provider) final;
+ void runInThread(QPromise<FileNameToContentsHash> &promise,
const Utils::FilePath &cmd, const Utils::FilePath &workDir,
const QStringList &args, const ContentProvider &provider,
const Utils::Environment &env);
diff --git a/src/plugins/projectexplorer/fileinsessionfinder.cpp b/src/plugins/projectexplorer/fileinsessionfinder.cpp
index 78f75ce1d5..d8df6c7430 100644
--- a/src/plugins/projectexplorer/fileinsessionfinder.cpp
+++ b/src/plugins/projectexplorer/fileinsessionfinder.cpp
@@ -4,7 +4,7 @@
#include "fileinsessionfinder.h"
#include "project.h"
-#include "session.h"
+#include "projectmanager.h"
#include <utils/fileinprojectfinder.h>
@@ -30,12 +30,12 @@ private:
FileInSessionFinder::FileInSessionFinder()
{
- connect(SessionManager::instance(), &SessionManager::projectAdded,
+ connect(ProjectManager::instance(), &ProjectManager::projectAdded,
this, [this](const Project *p) {
invalidateFinder();
connect(p, &Project::fileListChanged, this, &FileInSessionFinder::invalidateFinder);
});
- connect(SessionManager::instance(), &SessionManager::projectRemoved,
+ connect(ProjectManager::instance(), &ProjectManager::projectRemoved,
this, [this](const Project *p) {
invalidateFinder();
p->disconnect(this);
@@ -45,11 +45,11 @@ FileInSessionFinder::FileInSessionFinder()
FilePaths FileInSessionFinder::doFindFile(const FilePath &filePath)
{
if (!m_finderIsUpToDate) {
- m_finder.setProjectDirectory(SessionManager::startupProject()
- ? SessionManager::startupProject()->projectDirectory()
+ m_finder.setProjectDirectory(ProjectManager::startupProject()
+ ? ProjectManager::startupProject()->projectDirectory()
: FilePath());
FilePaths allFiles;
- for (const Project * const p : SessionManager::projects())
+ for (const Project * const p : ProjectManager::projects())
allFiles << p->files(Project::SourceFiles);
m_finder.setProjectFiles(allFiles);
m_finderIsUpToDate = true;
diff --git a/src/plugins/projectexplorer/filesinallprojectsfind.cpp b/src/plugins/projectexplorer/filesinallprojectsfind.cpp
index 720cfbabae..0f9d6c40e2 100644
--- a/src/plugins/projectexplorer/filesinallprojectsfind.cpp
+++ b/src/plugins/projectexplorer/filesinallprojectsfind.cpp
@@ -5,7 +5,7 @@
#include "project.h"
#include "projectexplorertr.h"
-#include "session.h"
+#include "projectmanager.h"
#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
@@ -52,7 +52,7 @@ Utils::FileIterator *FilesInAllProjectsFind::files(const QStringList &nameFilter
const QVariant &additionalParameters) const
{
Q_UNUSED(additionalParameters)
- const QSet<FilePath> dirs = Utils::transform<QSet>(SessionManager::projects(), [](Project *p) {
+ const QSet<FilePath> dirs = Utils::transform<QSet>(ProjectManager::projects(), [](Project *p) {
return p->projectFilePath().parentDir();
});
return new SubDirFileIterator(FilePaths(dirs.constBegin(), dirs.constEnd()),
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index d2449bd69a..4012fbd669 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -20,8 +20,8 @@
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <QBuffer>
#include <QCheckBox>
@@ -119,7 +119,7 @@ static QString runGcc(const FilePath &gcc, const QStringList &arguments, const E
if (!gcc.isExecutableFile())
return {};
- QtcProcess cpp;
+ Process cpp;
Environment environment(env);
environment.setupEnglishOutput();
@@ -196,7 +196,7 @@ HeaderPaths GccToolChain::gccHeaderPaths(const FilePath &gcc,
}
const FilePath headerPath
- = FilePath::fromString(QString::fromUtf8(line)).onDevice(gcc).canonicalPath();
+ = gcc.withNewPath(QString::fromUtf8(line)).canonicalPath();
if (!headerPath.isEmpty())
builtInHeaderPaths.append({headerPath, thisHeaderKind});
@@ -569,7 +569,7 @@ WarningFlags GccToolChain::warningFlags(const QStringList &cflags) const
return flags;
}
-QStringList GccToolChain::includedFiles(const QStringList &flags, const QString &directoryPath) const
+FilePaths GccToolChain::includedFiles(const QStringList &flags, const FilePath &directoryPath) const
{
return ToolChain::includedFiles("-include", flags, directoryPath, PossiblyConcatenatedFlag::No);
}
@@ -1040,10 +1040,9 @@ GccToolChainFactory::GccToolChainFactory()
Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector) const
{
// GCC is almost never what you want on macOS, but it is by default found in /usr/bin
- if (HostOsInfo::isMacHost()
- && (!detector.device || detector.device->type() == Constants::DESKTOP_DEVICE_TYPE)) {
+ if (HostOsInfo::isMacHost() && detector.device->type() == Constants::DESKTOP_DEVICE_TYPE)
return {};
- }
+
Toolchains tcs;
static const auto tcChecker = [](const ToolChain *tc) {
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor
@@ -1086,7 +1085,7 @@ static FilePaths findCompilerCandidates(const ToolchainDetector &detector,
{
const IDevice::ConstPtr device = detector.device;
const QFileInfo fi(compilerName);
- if (device.isNull() && fi.isAbsolute() && fi.isFile())
+ if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE && fi.isAbsolute() && fi.isFile())
return {FilePath::fromString(compilerName)};
QStringList nameFilters(compilerName);
@@ -1385,8 +1384,10 @@ void GccToolChainConfigWidget::setFromToolchain()
QSignalBlocker blocker(this);
auto tc = static_cast<GccToolChain *>(toolChain());
m_compilerCommand->setFilePath(tc->compilerCommand());
- m_platformCodeGenFlagsLineEdit->setText(ProcessArgs::joinArgs(tc->platformCodeGenFlags()));
- m_platformLinkerFlagsLineEdit->setText(ProcessArgs::joinArgs(tc->platformLinkerFlags()));
+ m_platformCodeGenFlagsLineEdit->setText(ProcessArgs::joinArgs(tc->platformCodeGenFlags(),
+ HostOsInfo::hostOs()));
+ m_platformLinkerFlagsLineEdit->setText(ProcessArgs::joinArgs(tc->platformLinkerFlags(),
+ HostOsInfo::hostOs()));
if (m_abiWidget) {
m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi());
if (!m_isReadOnly && !m_compilerCommand->filePath().toString().isEmpty())
@@ -1569,7 +1570,7 @@ bool ClangToolChain::matchesCompilerCommand(const FilePath &command) const
m_resolvedCompilerCommand = FilePath();
if (HostOsInfo::isMacHost()
&& compilerCommand().parentDir() == FilePath::fromString("/usr/bin")) {
- QtcProcess xcrun;
+ Process xcrun;
xcrun.setCommand({"/usr/bin/xcrun", {"-f", compilerCommand().fileName()}});
xcrun.runBlocking();
const FilePath output = FilePath::fromString(xcrun.cleanedStdOut().trimmed());
diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h
index 55ba61e9fb..1e6353d0a7 100644
--- a/src/plugins/projectexplorer/gcctoolchain.h
+++ b/src/plugins/projectexplorer/gcctoolchain.h
@@ -55,8 +55,8 @@ public:
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
Utils::WarningFlags warningFlags(const QStringList &cflags) const override;
- QStringList includedFiles(const QStringList &flags,
- const QString &directoryPath) const override;
+ Utils::FilePaths includedFiles(const QStringList &flags,
+ const Utils::FilePath &directoryPath) const override;
MacroInspectionRunner createMacroInspectionRunner() const override;
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(const Utils::Environment &env) const override;
diff --git a/src/plugins/projectexplorer/ipotentialkit.h b/src/plugins/projectexplorer/ipotentialkit.h
index ae032fb9e3..038a3a9fac 100644
--- a/src/plugins/projectexplorer/ipotentialkit.h
+++ b/src/plugins/projectexplorer/ipotentialkit.h
@@ -4,18 +4,16 @@
#pragma once
#include <QObject>
-#include <QMetaType>
+
#include "projectexplorer_export.h"
namespace ProjectExplorer {
-class PROJECTEXPLORER_EXPORT IPotentialKit : public QObject
+class PROJECTEXPLORER_EXPORT IPotentialKit
{
- Q_OBJECT
-
public:
IPotentialKit();
- ~IPotentialKit() override;
+ virtual ~IPotentialKit();
virtual QString displayName() const = 0;
virtual void executeFromMenu() = 0;
@@ -23,4 +21,4 @@ public:
virtual bool isEnabled() const = 0;
};
-}
+} // ProjectExplorer
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
index 25a897bd79..49a9571189 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
@@ -16,10 +16,7 @@
#include <utils/algorithm.h>
#include <utils/fancylineedit.h>
-#include <utils/fileutils.h>
#include <utils/qtcassert.h>
-#include <utils/runextensions.h>
-#include <utils/stringutils.h>
#include <utils/theme/theme.h>
#include <QApplication>
@@ -29,7 +26,6 @@
#include <QDebug>
#include <QDir>
#include <QFormLayout>
-#include <QFutureWatcher>
#include <QItemSelectionModel>
#include <QLabel>
#include <QListView>
@@ -603,25 +599,21 @@ void LineEditField::setupCompletion(FancyLineEdit *lineEdit)
using namespace Utils;
if (m_completion == Completion::None)
return;
- ILocatorFilter * const classesFilter = findOrDefault(
- ILocatorFilter::allLocatorFilters(),
- equal(&ILocatorFilter::id, Id("Classes")));
- if (!classesFilter)
- return;
- classesFilter->prepareSearch({});
- const auto watcher = new QFutureWatcher<LocatorFilterEntry>;
- const auto handleResults = [this, lineEdit, watcher](int firstIndex, int endIndex) {
+ LocatorMatcher *matcher = new LocatorMatcher;
+ matcher->setParent(lineEdit);
+ matcher->setTasks(LocatorMatcher::matchers(MatcherType::Classes));
+ const auto handleResults = [lineEdit, matcher, completion = m_completion] {
QSet<QString> namespaces;
QStringList classes;
Project * const project = ProjectTree::currentProject();
- for (int i = firstIndex; i < endIndex; ++i) {
+ const LocatorFilterEntries entries = matcher->outputData();
+ for (const LocatorFilterEntry &entry : entries) {
static const auto isReservedName = [](const QString &name) {
static const QRegularExpression rx1("^_[A-Z].*");
static const QRegularExpression rx2(".*::_[A-Z].*");
return name.contains("__") || rx1.match(name).hasMatch()
|| rx2.match(name).hasMatch();
};
- const LocatorFilterEntry &entry = watcher->resultAt(i);
const bool hasNamespace = !entry.extraInfo.isEmpty()
&& !entry.extraInfo.startsWith('<') && !entry.extraInfo.contains("::<")
&& !isReservedName(entry.extraInfo)
@@ -635,7 +627,7 @@ void LineEditField::setupCompletion(FancyLineEdit *lineEdit)
if (hasNamespace) {
if (isBaseClassCandidate)
classes << (entry.extraInfo + "::" + entry.displayName);
- if (m_completion == Completion::Namespaces) {
+ if (completion == Completion::Namespaces) {
if (!project
|| entry.filePath.startsWith(project->projectDirectory().toString())) {
namespaces << entry.extraInfo;
@@ -644,7 +636,7 @@ void LineEditField::setupCompletion(FancyLineEdit *lineEdit)
}
}
QStringList completionList;
- if (m_completion == Completion::Namespaces) {
+ if (completion == Completion::Namespaces) {
completionList = toList(namespaces);
completionList = filtered(completionList, [&classes](const QString &ns) {
return !classes.contains(ns);
@@ -658,16 +650,9 @@ void LineEditField::setupCompletion(FancyLineEdit *lineEdit)
completionList.sort();
lineEdit->setSpecialCompleter(new QCompleter(completionList, lineEdit));
};
- QObject::connect(watcher, &QFutureWatcher<LocatorFilterEntry>::resultsReadyAt, lineEdit,
- handleResults);
- QObject::connect(watcher, &QFutureWatcher<LocatorFilterEntry>::finished,
- watcher, &QFutureWatcher<LocatorFilterEntry>::deleteLater);
- watcher->setFuture(runAsync([classesFilter](QFutureInterface<LocatorFilterEntry> &f) {
- const QList<LocatorFilterEntry> matches = classesFilter->matchesFor(f, {});
- if (!matches.isEmpty())
- f.reportResults(QVector<LocatorFilterEntry>(matches.cbegin(), matches.cend()));
- f.reportFinished();
- }));
+ QObject::connect(matcher, &LocatorMatcher::done, lineEdit, handleResults);
+ QObject::connect(matcher, &LocatorMatcher::done, matcher, &QObject::deleteLater);
+ matcher->start();
}
void LineEditField::setText(const QString &text)
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp
index 024044d7a0..ec55e3218f 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp
@@ -8,8 +8,8 @@
#include "../projectexplorerconstants.h"
#include "../projectexplorertr.h"
#include "../projectnodes.h"
+#include "../projectmanager.h"
#include "../projecttree.h"
-#include "../session.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/iversioncontrol.h>
@@ -209,7 +209,7 @@ Node *JsonSummaryPage::findWizardContextNode(Node *contextNode) const
// Static cast from void * to avoid qobject_cast (which needs a valid object) in value().
auto project = static_cast<Project *>(m_wizard->value(Constants::PROJECT_POINTER).value<void *>());
- if (SessionManager::projects().contains(project) && project->rootProjectNode()) {
+ if (ProjectManager::projects().contains(project) && project->rootProjectNode()) {
const FilePath path = FilePath::fromVariant(m_wizard->value(Constants::PREFERRED_PROJECT_NODE_PATH));
contextNode = project->rootProjectNode()->findNode([path](const Node *n) {
return path == n->filePath();
diff --git a/src/plugins/projectexplorer/kitchooser.cpp b/src/plugins/projectexplorer/kitchooser.cpp
index 14c848da74..9e45cacd7d 100644
--- a/src/plugins/projectexplorer/kitchooser.cpp
+++ b/src/plugins/projectexplorer/kitchooser.cpp
@@ -6,7 +6,7 @@
#include "kitmanager.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
-#include "session.h"
+#include "projectmanager.h"
#include "target.h"
#include <coreplugin/icore.h>
@@ -88,7 +88,7 @@ void KitChooser::populate()
const Id lastKit = Id::fromSetting(ICore::settings()->value(lastKitKey));
bool didActivate = false;
- if (Target *target = SessionManager::startupTarget()) {
+ if (Target *target = ProjectManager::startupTarget()) {
Kit *kit = target->kit();
if (m_kitPredicate(kit)) {
QString display = Tr::tr("Kit of Active Project: %1").arg(kitText(kit));
diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp
index dcb490b70d..fc8039b402 100644
--- a/src/plugins/projectexplorer/kitinformation.cpp
+++ b/src/plugins/projectexplorer/kitinformation.cpp
@@ -34,7 +34,6 @@
#include <QVBoxLayout>
using namespace Utils;
-using namespace Utils::Layouting;
namespace ProjectExplorer {
@@ -65,7 +64,7 @@ public:
private:
void makeReadOnly() override { m_chooser->setReadOnly(true); }
- void addToLayout(LayoutBuilder &builder) override
+ void addToLayout(Layouting::LayoutItem &builder) override
{
addMutableAction(m_chooser);
builder.addItem(Layouting::Span(2, m_chooser));
@@ -142,7 +141,7 @@ void SysRootKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) con
});
}
-Id SysRootKitAspect::id()
+Utils::Id SysRootKitAspect::id()
{
return "PE.Profile.SysRoot";
}
@@ -231,7 +230,7 @@ public:
}
private:
- void addToLayout(LayoutBuilder &builder) override
+ void addToLayout(Layouting::LayoutItem &builder) override
{
addMutableAction(m_mainWidget);
builder.addItem(m_mainWidget);
@@ -760,7 +759,7 @@ public:
~DeviceTypeKitAspectWidget() override { delete m_comboBox; }
private:
- void addToLayout(LayoutBuilder &builder) override
+ void addToLayout(Layouting::LayoutItem &builder) override
{
addMutableAction(m_comboBox);
builder.addItem(m_comboBox);
@@ -795,7 +794,7 @@ DeviceTypeKitAspect::DeviceTypeKitAspect()
{
setObjectName(QLatin1String("DeviceTypeInformation"));
setId(DeviceTypeKitAspect::id());
- setDisplayName(Tr::tr("Device type"));
+ setDisplayName(Tr::tr("Run device type"));
setDescription(Tr::tr("The type of device to run applications on."));
setPriority(33000);
makeEssential();
@@ -896,7 +895,7 @@ public:
}
private:
- void addToLayout(LayoutBuilder &builder) override
+ void addToLayout(Layouting::LayoutItem &builder) override
{
addMutableAction(m_comboBox);
builder.addItem(m_comboBox);
@@ -942,7 +941,7 @@ DeviceKitAspect::DeviceKitAspect()
{
setObjectName(QLatin1String("DeviceInformation"));
setId(DeviceKitAspect::id());
- setDisplayName(Tr::tr("Device"));
+ setDisplayName(Tr::tr("Run device"));
setDescription(Tr::tr("The device to run the applications on."));
setPriority(32000);
@@ -1023,30 +1022,29 @@ KitAspect::ItemList DeviceKitAspect::toUserOutput(const Kit *k) const
void DeviceKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) const
{
QTC_ASSERT(kit, return);
- expander->registerVariable("Device:HostAddress", Tr::tr("Host address"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
- return device ? device->sshParameters().host() : QString();
+ expander->registerVariable("Device:HostAddress", Tr::tr("Host address"), [kit] {
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
+ return device ? device->sshParameters().host() : QString();
});
- expander->registerVariable("Device:SshPort", Tr::tr("SSH port"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
- return device ? QString::number(device->sshParameters().port()) : QString();
+ expander->registerVariable("Device:SshPort", Tr::tr("SSH port"), [kit] {
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
+ return device ? QString::number(device->sshParameters().port()) : QString();
});
- expander->registerVariable("Device:UserName", Tr::tr("User name"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
- return device ? device->sshParameters().userName() : QString();
+ expander->registerVariable("Device:UserName", Tr::tr("User name"), [kit] {
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
+ return device ? device->sshParameters().userName() : QString();
});
- expander->registerVariable("Device:KeyFile", Tr::tr("Private key file"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
- return device ? device->sshParameters().privateKeyFile.toString() : QString();
+ expander->registerVariable("Device:KeyFile", Tr::tr("Private key file"), [kit] {
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
+ return device ? device->sshParameters().privateKeyFile.toString() : QString();
});
- expander->registerVariable("Device:Name", Tr::tr("Device name"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
- return device ? device->displayName() : QString();
+ expander->registerVariable("Device:Name", Tr::tr("Device name"), [kit] {
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
+ return device ? device->displayName() : QString();
+ });
+ expander->registerFileVariables("Device::Root", Tr::tr("Device root directory"), [kit] {
+ const IDevice::ConstPtr device = DeviceKitAspect::device(kit);
+ return device ? device->rootPath() : FilePath{};
});
}
@@ -1157,7 +1155,7 @@ public:
}
private:
- void addToLayout(LayoutBuilder &builder) override
+ void addToLayout(Layouting::LayoutItem &builder) override
{
addMutableAction(m_comboBox);
builder.addItem(m_comboBox);
@@ -1266,31 +1264,31 @@ KitAspect::ItemList BuildDeviceKitAspect::toUserOutput(const Kit *k) const
void BuildDeviceKitAspect::addToMacroExpander(Kit *kit, MacroExpander *expander) const
{
QTC_ASSERT(kit, return);
- expander->registerVariable("BuildDevice:HostAddress", Tr::tr("Build host address"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
- return device ? device->sshParameters().host() : QString();
+ expander->registerVariable("BuildDevice:HostAddress", Tr::tr("Build host address"), [kit] {
+ const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
+ return device ? device->sshParameters().host() : QString();
});
- expander->registerVariable("BuildDevice:SshPort", Tr::tr("Build SSH port"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
- return device ? QString::number(device->sshParameters().port()) : QString();
+ expander->registerVariable("BuildDevice:SshPort", Tr::tr("Build SSH port"), [kit] {
+ const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
+ return device ? QString::number(device->sshParameters().port()) : QString();
});
- expander->registerVariable("BuildDevice:UserName", Tr::tr("Build user name"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
- return device ? device->sshParameters().userName() : QString();
+ expander->registerVariable("BuildDevice:UserName", Tr::tr("Build user name"), [kit] {
+ const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
+ return device ? device->sshParameters().userName() : QString();
});
- expander->registerVariable("BuildDevice:KeyFile", Tr::tr("Build private key file"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
- return device ? device->sshParameters().privateKeyFile.toString() : QString();
+ expander->registerVariable("BuildDevice:KeyFile", Tr::tr("Build private key file"), [kit] {
+ const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
+ return device ? device->sshParameters().privateKeyFile.toString() : QString();
});
- expander->registerVariable("BuildDevice:Name", Tr::tr("Build device name"),
- [kit]() -> QString {
- const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
- return device ? device->displayName() : QString();
+ expander->registerVariable("BuildDevice:Name", Tr::tr("Build device name"), [kit] {
+ const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
+ return device ? device->displayName() : QString();
});
+ expander
+ ->registerFileVariables("BuildDevice::Root", Tr::tr("Build device root directory"), [kit] {
+ const IDevice::ConstPtr device = BuildDeviceKitAspect::device(kit);
+ return device ? device->rootPath() : FilePath{};
+ });
}
Id BuildDeviceKitAspect::id()
@@ -1388,7 +1386,7 @@ public:
}
private:
- void addToLayout(LayoutBuilder &builder) override
+ void addToLayout(Layouting::LayoutItem &builder) override
{
addMutableAction(m_mainWidget);
builder.addItem(m_mainWidget);
diff --git a/src/plugins/projectexplorer/kitmanager.cpp b/src/plugins/projectexplorer/kitmanager.cpp
index cb67e11fac..86a3b533c1 100644
--- a/src/plugins/projectexplorer/kitmanager.cpp
+++ b/src/plugins/projectexplorer/kitmanager.cpp
@@ -747,7 +747,7 @@ KitAspectWidget::~KitAspectWidget()
delete m_mutableAction;
}
-void KitAspectWidget::addToLayoutWithLabel(QWidget *parent)
+void KitAspectWidget::addToLayoutWithLabel(Layouting::LayoutItem &parentItem, QWidget *parent)
{
QTC_ASSERT(parent, return);
auto label = createSubWidget<QLabel>(m_kitInformation->displayName() + ':');
@@ -756,10 +756,9 @@ void KitAspectWidget::addToLayoutWithLabel(QWidget *parent)
emit labelLinkActivated(link);
});
- Layouting::LayoutExtender builder(parent->layout(), Layouting::WithFormAlignment);
- builder.finishRow();
- builder.addItem(label);
- addToLayout(builder);
+ parentItem.addItem(label);
+ addToLayout(parentItem);
+ parentItem.addItem(Layouting::br);
}
void KitAspectWidget::addMutableAction(QWidget *child)
diff --git a/src/plugins/projectexplorer/kitmanager.h b/src/plugins/projectexplorer/kitmanager.h
index a494fde323..f25f83ca7f 100644
--- a/src/plugins/projectexplorer/kitmanager.h
+++ b/src/plugins/projectexplorer/kitmanager.h
@@ -117,7 +117,7 @@ public:
virtual void makeReadOnly() = 0;
virtual void refresh() = 0;
- void addToLayoutWithLabel(QWidget *parent);
+ void addToLayoutWithLabel(Layouting::LayoutItem &parentItem, QWidget *parent);
static QString msgManage();
diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
index 908238d3a7..822844f57d 100644
--- a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
+++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
@@ -23,6 +23,7 @@
#include <QRegularExpression>
#include <QRegularExpressionValidator>
#include <QFileDialog>
+#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
@@ -36,12 +37,14 @@ using namespace Utils;
namespace ProjectExplorer {
namespace Internal {
-KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
+KitManagerConfigWidget::KitManagerConfigWidget(Kit *k, bool &isDefaultKit, bool &hasUniqueName) :
m_iconButton(new QToolButton),
m_nameEdit(new QLineEdit),
m_fileSystemFriendlyNameLineEdit(new QLineEdit),
m_kit(k),
- m_modifiedKit(std::make_unique<Kit>(Utils::Id(WORKING_COPY_KIT_ID)))
+ m_modifiedKit(std::make_unique<Kit>(Utils::Id(WORKING_COPY_KIT_ID))),
+ m_isDefaultKit(isDefaultKit),
+ m_hasUniqueName(hasUniqueName)
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
@@ -64,10 +67,13 @@ KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
this, &KitManagerConfigWidget::setFileSystemFriendlyName);
using namespace Layouting;
- Grid {
+ Grid page {
+ withFormAlignment,
+ columnStretch(1, 2),
label, m_nameEdit, m_iconButton, br,
- fsLabel, m_fileSystemFriendlyNameLineEdit
- }.attachTo(this, WithFormAlignment);
+ fsLabel, m_fileSystemFriendlyNameLineEdit, br,
+ noMargin
+ };
m_iconButton->setToolTip(Tr::tr("Kit icon."));
auto setIconAction = new QAction(Tr::tr("Select Icon..."), this);
@@ -97,7 +103,9 @@ KitManagerConfigWidget::KitManagerConfigWidget(Kit *k) :
chooser->addMacroExpanderProvider([this] { return m_modifiedKit->macroExpander(); });
for (KitAspect *aspect : KitManager::kitAspects())
- addAspectToWorkingCopy(aspect);
+ addAspectToWorkingCopy(page, aspect);
+
+ page.attachTo(this);
updateVisibility();
@@ -187,14 +195,14 @@ QString KitManagerConfigWidget::validityMessage() const
return m_modifiedKit->toHtml(tmp);
}
-void KitManagerConfigWidget::addAspectToWorkingCopy(KitAspect *aspect)
+void KitManagerConfigWidget::addAspectToWorkingCopy(Layouting::LayoutItem &parent, KitAspect *aspect)
{
QTC_ASSERT(aspect, return);
KitAspectWidget *widget = aspect->createConfigWidget(workingCopy());
QTC_ASSERT(widget, return);
QTC_ASSERT(!m_widgets.contains(widget), return);
- widget->addToLayoutWithLabel(this);
+ widget->addToLayoutWithLabel(parent, this);
m_widgets.append(widget);
connect(widget->mutableAction(), &QAction::toggled,
@@ -213,11 +221,6 @@ void KitManagerConfigWidget::updateVisibility()
}
}
-void KitManagerConfigWidget::setHasUniqueName(bool unique)
-{
- m_hasUniqueName = unique;
-}
-
void KitManagerConfigWidget::makeStickySubWidgetsReadOnly()
{
for (KitAspectWidget *w : std::as_const(m_widgets)) {
@@ -231,31 +234,11 @@ Kit *KitManagerConfigWidget::workingCopy() const
return m_modifiedKit.get();
}
-bool KitManagerConfigWidget::configures(Kit *k) const
-{
- return m_kit == k;
-}
-
-void KitManagerConfigWidget::setIsDefaultKit(bool d)
-{
- if (m_isDefaultKit == d)
- return;
- m_isDefaultKit = d;
- emit dirty();
-}
-
bool KitManagerConfigWidget::isDefaultKit() const
{
return m_isDefaultKit;
}
-void KitManagerConfigWidget::removeKit()
-{
- if (!m_kit)
- return;
- KitManager::deregisterKit(m_kit);
-}
-
void KitManagerConfigWidget::setIcon()
{
const Utils::Id deviceType = DeviceTypeKitAspect::deviceTypeId(m_modifiedKit.get());
diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.h b/src/plugins/projectexplorer/kitmanagerconfigwidget.h
index 142eb8fa36..94218c5de8 100644
--- a/src/plugins/projectexplorer/kitmanagerconfigwidget.h
+++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.h
@@ -25,7 +25,7 @@ class KitManagerConfigWidget : public QWidget
Q_OBJECT
public:
- explicit KitManagerConfigWidget(Kit *k);
+ explicit KitManagerConfigWidget(Kit *k, bool &isDefaultKit, bool &hasUniqueName);
~KitManagerConfigWidget() override;
QString displayName() const;
@@ -35,19 +35,14 @@ public:
void discard();
bool isDirty() const;
QString validityMessage() const;
- void addAspectToWorkingCopy(KitAspect *aspect);
+ void addAspectToWorkingCopy(Layouting::LayoutItem &parent, KitAspect *aspect);
void makeStickySubWidgetsReadOnly();
Kit *workingCopy() const;
- bool configures(Kit *k) const;
bool isRegistering() const { return m_isRegistering; }
- void setIsDefaultKit(bool d);
bool isDefaultKit() const;
- void removeKit();
void updateVisibility();
- void setHasUniqueName(bool unique);
-
signals:
void dirty();
void isAutoDetectedChanged();
@@ -74,9 +69,9 @@ private:
QList<KitAspectWidget *> m_widgets;
Kit *m_kit;
std::unique_ptr<Kit> m_modifiedKit;
- bool m_isDefaultKit = false;
+ bool &m_isDefaultKit;
bool m_fixingKit = false;
- bool m_hasUniqueName = true;
+ bool &m_hasUniqueName;
bool m_isRegistering = false;
mutable QString m_cachedDisplayName;
};
diff --git a/src/plugins/projectexplorer/kitmodel.cpp b/src/plugins/projectexplorer/kitmodel.cpp
index 4b250f23c9..12f23fb281 100644
--- a/src/plugins/projectexplorer/kitmodel.cpp
+++ b/src/plugins/projectexplorer/kitmodel.cpp
@@ -24,57 +24,122 @@ namespace Internal {
class KitNode : public TreeItem
{
public:
- KitNode(Kit *k, KitModel *m)
+ KitNode(Kit *k, KitModel *m, QBoxLayout *parentLayout)
+ : m_kit(k), m_model(m), m_parentLayout(parentLayout)
+ {}
+
+ ~KitNode() override { delete m_widget; }
+
+ Kit *kit() const { return m_kit; }
+
+ QVariant data(int, int role) const override
{
- widget = new KitManagerConfigWidget(k);
+ if (role == Qt::FontRole) {
+ QFont f = QApplication::font();
+ if (isDirty())
+ f.setBold(!f.bold());
+ if (isDefaultKit())
+ f.setItalic(f.style() != QFont::StyleItalic);
+ return f;
+ }
+ if (role == Qt::DisplayRole) {
+ QString baseName = displayName();
+ if (isDefaultKit())
+ //: Mark up a kit as the default one.
+ baseName = Tr::tr("%1 (default)").arg(baseName);
+ return baseName;
+ }
- QObject::connect(widget, &KitManagerConfigWidget::dirty, m, [this] { update(); });
+ if (role == Qt::DecorationRole)
+ return displayIcon();
- QObject::connect(widget, &KitManagerConfigWidget::isAutoDetectedChanged, m, [this, m] {
- TreeItem *oldParent = parent();
- TreeItem *newParent =
- m->rootItem()->childAt(widget->workingCopy()->isAutoDetected() ? 0 : 1);
- if (oldParent && oldParent != newParent) {
- m->takeItem(this);
- newParent->appendChild(this);
- }
- });
+ if (role == Qt::ToolTipRole)
+ return widget()->validityMessage();
+
+ return {};
}
- ~KitNode() override
+ bool isDirty() const
{
- delete widget;
+ if (m_widget)
+ return m_widget->isDirty();
+ return false;
}
- QVariant data(int, int role) const override
+ QIcon displayIcon() const
{
- if (widget) {
- if (role == Qt::FontRole) {
- QFont f = QApplication::font();
- if (widget->isDirty())
- f.setBold(!f.bold());
- if (widget->isDefaultKit())
- f.setItalic(f.style() != QFont::StyleItalic);
- return f;
- }
- if (role == Qt::DisplayRole) {
- QString baseName = widget->displayName();
- if (widget->isDefaultKit())
- //: Mark up a kit as the default one.
- baseName = Tr::tr("%1 (default)").arg(baseName);
- return baseName;
- }
- if (role == Qt::DecorationRole) {
- return widget->displayIcon();
- }
- if (role == Qt::ToolTipRole) {
- return widget->validityMessage();
+ if (m_widget)
+ return m_widget->displayIcon();
+ return m_kit->displayIcon();
+ }
+
+ QString displayName() const
+ {
+ if (m_widget)
+ return m_widget->displayName();
+ return m_kit->displayName();
+ }
+
+ bool isDefaultKit() const
+ {
+ return m_isDefaultKit;
+ }
+
+ bool isRegistering() const
+ {
+ if (m_widget)
+ return m_widget->isRegistering();
+ return false;
+ }
+
+ void setIsDefaultKit(bool on)
+ {
+ if (m_isDefaultKit == on)
+ return;
+ m_isDefaultKit = on;
+ if (m_widget)
+ emit m_widget->dirty();
+ }
+
+ KitManagerConfigWidget *widget() const
+ {
+ const_cast<KitNode *>(this)->ensureWidget();
+ return m_widget;
+ }
+
+ void setHasUniqueName(bool on)
+ {
+ m_hasUniqueName = on;
+ }
+
+private:
+ void ensureWidget()
+ {
+ if (m_widget)
+ return;
+
+ m_widget = new KitManagerConfigWidget(m_kit, m_isDefaultKit, m_hasUniqueName);
+
+ QObject::connect(m_widget, &KitManagerConfigWidget::dirty, m_model, [this] { update(); });
+
+ QObject::connect(m_widget, &KitManagerConfigWidget::isAutoDetectedChanged, m_model, [this] {
+ TreeItem *oldParent = parent();
+ TreeItem *newParent =
+ m_model->rootItem()->childAt(m_widget->workingCopy()->isAutoDetected() ? 0 : 1);
+ if (oldParent && oldParent != newParent) {
+ m_model->takeItem(this);
+ newParent->appendChild(this);
}
- }
- return QVariant();
+ });
+ m_parentLayout->addWidget(m_widget);
}
- KitManagerConfigWidget *widget;
+ Kit *m_kit = m_kit;
+ KitModel *m_model = nullptr;
+ KitManagerConfigWidget *m_widget = nullptr;
+ QBoxLayout *m_parentLayout = nullptr;
+ bool m_isDefaultKit = false;
+ bool m_hasUniqueName = true;
};
// --------------------------------------------------------------------------
@@ -113,7 +178,7 @@ KitModel::KitModel(QBoxLayout *parentLayout, QObject *parent)
Kit *KitModel::kit(const QModelIndex &index)
{
KitNode *n = kitNode(index);
- return n ? n->widget->workingCopy() : nullptr;
+ return n ? n->widget()->workingCopy() : nullptr;
}
KitNode *KitModel::kitNode(const QModelIndex &index)
@@ -136,20 +201,20 @@ void KitModel::setDefaultKit(const QModelIndex &index)
bool KitModel::isDefaultKit(Kit *k) const
{
- return m_defaultNode && m_defaultNode->widget->workingCopy() == k;
+ return m_defaultNode && m_defaultNode->widget()->workingCopy() == k;
}
KitManagerConfigWidget *KitModel::widget(const QModelIndex &index)
{
KitNode *n = kitNode(index);
- return n ? n->widget : nullptr;
+ return n ? n->widget() : nullptr;
}
void KitModel::validateKitNames()
{
QHash<QString, int> nameHash;
forItemsAtLevel<2>([&nameHash](KitNode *n) {
- const QString displayName = n->widget->displayName();
+ const QString displayName = n->displayName();
if (nameHash.contains(displayName))
++nameHash[displayName];
else
@@ -157,8 +222,8 @@ void KitModel::validateKitNames()
});
forItemsAtLevel<2>([&nameHash](KitNode *n) {
- const QString displayName = n->widget->displayName();
- n->widget->setHasUniqueName(nameHash.value(displayName) == 1);
+ const QString displayName = n->displayName();
+ n->setHasUniqueName(nameHash.value(displayName) == 1);
});
}
@@ -166,8 +231,8 @@ void KitModel::apply()
{
// Add/update dirty nodes before removing kits. This ensures the right kit ends up as default.
forItemsAtLevel<2>([](KitNode *n) {
- if (n->widget->isDirty()) {
- n->widget->apply();
+ if (n->isDirty()) {
+ n->widget()->apply();
n->update();
}
});
@@ -175,7 +240,7 @@ void KitModel::apply()
// Remove unused kits:
const QList<KitNode *> removeList = m_toRemoveList;
for (KitNode *n : removeList)
- n->widget->removeKit();
+ KitManager::deregisterKit(n->kit());
emit layoutChanged(); // Force update.
}
@@ -197,7 +262,7 @@ void KitModel::markForRemoval(Kit *k)
setDefaultNode(findItemAtLevel<2>([node](KitNode *kn) { return kn != node; }));
takeItem(node);
- if (node->widget->configures(nullptr))
+ if (node->kit() == nullptr)
delete node;
else
m_toRemoveList.append(node);
@@ -209,7 +274,7 @@ Kit *KitModel::markForAddition(Kit *baseKit)
const QString newName = newKitName(baseKit ? baseKit->unexpandedDisplayName() : QString());
KitNode *node = createNode(nullptr);
m_manualRoot->appendChild(node);
- Kit *k = node->widget->workingCopy();
+ Kit *k = node->widget()->workingCopy();
KitGuard g(k);
if (baseKit) {
k->copyFrom(baseKit);
@@ -229,7 +294,7 @@ Kit *KitModel::markForAddition(Kit *baseKit)
void KitModel::updateVisibility()
{
forItemsAtLevel<2>([](const TreeItem *ti) {
- static_cast<const KitNode *>(ti)->widget->updateVisibility();
+ static_cast<const KitNode *>(ti)->widget()->updateVisibility();
});
}
@@ -237,32 +302,31 @@ QString KitModel::newKitName(const QString &sourceName) const
{
QList<Kit *> allKits;
forItemsAtLevel<2>([&allKits](const TreeItem *ti) {
- allKits << static_cast<const KitNode *>(ti)->widget->workingCopy();
+ allKits << static_cast<const KitNode *>(ti)->widget()->workingCopy();
});
return Kit::newKitName(sourceName, allKits);
}
KitNode *KitModel::findWorkingCopy(Kit *k) const
{
- return findItemAtLevel<2>([k](KitNode *n) { return n->widget->workingCopy() == k; });
+ return findItemAtLevel<2>([k](KitNode *n) { return n->widget()->workingCopy() == k; });
}
KitNode *KitModel::createNode(Kit *k)
{
- auto node = new KitNode(k, this);
- m_parentLayout->addWidget(node->widget);
+ auto node = new KitNode(k, this, m_parentLayout);
return node;
}
void KitModel::setDefaultNode(KitNode *node)
{
if (m_defaultNode) {
- m_defaultNode->widget->setIsDefaultKit(false);
+ m_defaultNode->setIsDefaultKit(false);
m_defaultNode->update();
}
m_defaultNode = node;
if (m_defaultNode) {
- m_defaultNode->widget->setIsDefaultKit(true);
+ m_defaultNode->setIsDefaultKit(true);
m_defaultNode->update();
}
}
@@ -271,7 +335,7 @@ void KitModel::addKit(Kit *k)
{
for (TreeItem *n : *m_manualRoot) {
// Was added by us
- if (static_cast<KitNode *>(n)->widget->isRegistering())
+ if (static_cast<KitNode *>(n)->isRegistering())
return;
}
@@ -292,7 +356,7 @@ void KitModel::removeKit(Kit *k)
{
QList<KitNode *> nodes = m_toRemoveList;
for (KitNode *n : std::as_const(nodes)) {
- if (n->widget->configures(k)) {
+ if (n->kit() == k) {
m_toRemoveList.removeOne(n);
if (m_defaultNode == n)
m_defaultNode = nullptr;
@@ -303,7 +367,7 @@ void KitModel::removeKit(Kit *k)
}
KitNode *node = findItemAtLevel<2>([k](KitNode *n) {
- return n->widget->configures(k);
+ return n->kit() == k;
});
if (node == m_defaultNode)
@@ -319,7 +383,7 @@ void KitModel::changeDefaultKit()
{
Kit *defaultKit = KitManager::defaultKit();
KitNode *node = findItemAtLevel<2>([defaultKit](KitNode *n) {
- return n->widget->configures(defaultKit);
+ return n->kit() == defaultKit;
});
setDefaultNode(node);
}
diff --git a/src/plugins/projectexplorer/kitoptionspage.cpp b/src/plugins/projectexplorer/kitoptionspage.cpp
index d5c709194a..db578a403e 100644
--- a/src/plugins/projectexplorer/kitoptionspage.cpp
+++ b/src/plugins/projectexplorer/kitoptionspage.cpp
@@ -23,11 +23,13 @@
namespace ProjectExplorer {
namespace Internal {
-// --------------------------------------------------------------------------
-// KitOptionsPageWidget:
-// --------------------------------------------------------------------------
+// KitOptionsPageWidget
+
+class KitOptionsPageWidget;
-class KitOptionsPageWidget : public QWidget
+static QPointer<KitOptionsPageWidget> kitOptionsPageWidget;
+
+class KitOptionsPageWidget : public Core::IOptionsPageWidget
{
public:
KitOptionsPageWidget();
@@ -42,6 +44,8 @@ public:
void makeDefaultKit();
void updateState();
+ void apply() final { m_model->apply(); }
+
public:
QTreeView *m_kitsView = nullptr;
QPushButton *m_addButton = nullptr;
@@ -58,6 +62,7 @@ public:
KitOptionsPageWidget::KitOptionsPageWidget()
{
+ kitOptionsPageWidget = this;
m_kitsView = new QTreeView(this);
m_kitsView->setUniformRowHeights(true);
m_kitsView->header()->setStretchLastSection(true);
@@ -239,38 +244,14 @@ QModelIndex KitOptionsPageWidget::currentIndex() const
// KitOptionsPage:
// --------------------------------------------------------------------------
-static KitOptionsPage *theKitOptionsPage = nullptr;
-
KitOptionsPage::KitOptionsPage()
{
- theKitOptionsPage = this;
setId(Constants::KITS_SETTINGS_PAGE_ID);
setDisplayName(Tr::tr("Kits"));
setCategory(Constants::KITS_SETTINGS_CATEGORY);
setDisplayCategory(Tr::tr("Kits"));
setCategoryIconPath(":/projectexplorer/images/settingscategory_kits.png");
-}
-
-QWidget *KitOptionsPage::widget()
-{
- if (!m_widget)
- m_widget = new Internal::KitOptionsPageWidget;
-
- return m_widget;
-}
-
-void KitOptionsPage::apply()
-{
- if (m_widget)
- m_widget->m_model->apply();
-}
-
-void KitOptionsPage::finish()
-{
- if (m_widget) {
- delete m_widget;
- m_widget = nullptr;
- }
+ setWidgetCreator([] { return new Internal::KitOptionsPageWidget; });
}
void KitOptionsPage::showKit(Kit *k)
@@ -278,18 +259,16 @@ void KitOptionsPage::showKit(Kit *k)
if (!k)
return;
- (void) widget();
- QModelIndex index = m_widget->m_model->indexOf(k);
- m_widget->m_selectionModel->select(index,
+ Internal::KitOptionsPageWidget *widget = Internal::kitOptionsPageWidget;
+ if (!widget)
+ return;
+
+ QModelIndex index = widget->m_model->indexOf(k);
+ widget->m_selectionModel->select(index,
QItemSelectionModel::Clear
| QItemSelectionModel::SelectCurrent
| QItemSelectionModel::Rows);
- m_widget->m_kitsView->scrollTo(index);
-}
-
-KitOptionsPage *KitOptionsPage::instance()
-{
- return theKitOptionsPage;
+ widget->m_kitsView->scrollTo(index);
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kitoptionspage.h b/src/plugins/projectexplorer/kitoptionspage.h
index 5ce589cd6b..a7a4ba29db 100644
--- a/src/plugins/projectexplorer/kitoptionspage.h
+++ b/src/plugins/projectexplorer/kitoptionspage.h
@@ -7,12 +7,8 @@
#include <coreplugin/dialogs/ioptionspage.h>
-#include <QPointer>
-
namespace ProjectExplorer {
-namespace Internal { class KitOptionsPageWidget; }
-
class Kit;
class PROJECTEXPLORER_EXPORT KitOptionsPage : public Core::IOptionsPage
@@ -20,15 +16,7 @@ class PROJECTEXPLORER_EXPORT KitOptionsPage : public Core::IOptionsPage
public:
KitOptionsPage();
- QWidget *widget() override;
- void apply() override;
- void finish() override;
-
- void showKit(Kit *k);
- static KitOptionsPage *instance();
-
-private:
- QPointer<Internal::KitOptionsPageWidget> m_widget;
+ static void showKit(Kit *k);
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/localenvironmentaspect.cpp b/src/plugins/projectexplorer/localenvironmentaspect.cpp
deleted file mode 100644
index 7510d636e5..0000000000
--- a/src/plugins/projectexplorer/localenvironmentaspect.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "localenvironmentaspect.h"
-
-#include "buildconfiguration.h"
-#include "kit.h"
-#include "projectexplorertr.h"
-#include "target.h"
-
-using namespace Utils;
-
-namespace ProjectExplorer {
-
-LocalEnvironmentAspect::LocalEnvironmentAspect(Target *target, bool includeBuildEnvironment)
-{
- setIsLocal(true);
- addSupportedBaseEnvironment(Tr::tr("Clean Environment"), {});
-
- addSupportedBaseEnvironment(Tr::tr("System Environment"), [] {
- return Environment::systemEnvironment();
- });
-
- if (includeBuildEnvironment) {
- addPreferredBaseEnvironment(Tr::tr("Build Environment"), [target] {
- Environment env;
- if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
- env = bc->environment();
- } else { // Fallback for targets without buildconfigurations:
- env = target->kit()->buildEnvironment();
- }
- return env;
- });
-
- connect(target,
- &Target::activeBuildConfigurationChanged,
- this,
- &EnvironmentAspect::environmentChanged);
- connect(target,
- &Target::buildEnvironmentChanged,
- this,
- &EnvironmentAspect::environmentChanged);
- }
-}
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/localenvironmentaspect.h b/src/plugins/projectexplorer/localenvironmentaspect.h
deleted file mode 100644
index ffe2556947..0000000000
--- a/src/plugins/projectexplorer/localenvironmentaspect.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "environmentaspect.h"
-
-namespace ProjectExplorer {
-
-class PROJECTEXPLORER_EXPORT LocalEnvironmentAspect : public EnvironmentAspect
-{
- Q_OBJECT
-
-public:
- explicit LocalEnvironmentAspect(Target *parent, bool includeBuildEnvironment = true);
-};
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp
index 57ebc2490b..ee9ffea832 100644
--- a/src/plugins/projectexplorer/makestep.cpp
+++ b/src/plugins/projectexplorer/makestep.cpp
@@ -18,13 +18,10 @@
#include <utils/hostosinfo.h>
#include <utils/layoutbuilder.h>
#include <utils/pathchooser.h>
-#include <utils/qtcprocess.h>
+#include <utils/process.h>
#include <utils/utilsicons.h>
#include <utils/variablechooser.h>
-#include <QCheckBox>
-#include <QLabel>
-#include <QLineEdit>
#include <QThread>
#include <optional>
@@ -49,9 +46,8 @@ MakeStep::MakeStep(BuildStepList *parent, Id id)
setCommandLineProvider([this] { return effectiveMakeCommand(Execution); });
- m_makeCommandAspect = addAspect<StringAspect>();
+ m_makeCommandAspect = addAspect<FilePathAspect>();
m_makeCommandAspect->setSettingsKey(id.withSuffix(MAKE_COMMAND_SUFFIX).toString());
- m_makeCommandAspect->setDisplayStyle(StringAspect::PathChooserDisplay);
m_makeCommandAspect->setExpectedKind(PathChooser::ExistingCommand);
m_makeCommandAspect->setBaseFileName(PathChooser::homePath());
m_makeCommandAspect->setHistoryCompleter("PE.MakeCommand.History");
@@ -318,14 +314,15 @@ CommandLine MakeStep::effectiveMakeCommand(MakeCommandType type) const
QWidget *MakeStep::createConfigWidget()
{
Layouting::Form builder;
- builder.addRow(m_makeCommandAspect);
- builder.addRow(m_userArgumentsAspect);
+ builder.addRow({m_makeCommandAspect});
+ builder.addRow({m_userArgumentsAspect});
builder.addRow({m_userJobCountAspect, m_overrideMakeflagsAspect, m_nonOverrideWarning});
if (m_disablingForSubDirsSupported)
- builder.addRow(m_disabledForSubdirsAspect);
- builder.addRow(m_buildTargetsAspect);
+ builder.addRow({m_disabledForSubdirsAspect});
+ builder.addRow({m_buildTargetsAspect});
+ builder.addItem(Layouting::noMargin);
- auto widget = builder.emerge(Layouting::WithoutMargins);
+ auto widget = builder.emerge();
VariableChooser::addSupportForChildWidgets(widget, macroExpander());
@@ -383,22 +380,6 @@ QWidget *MakeStep::createConfigWidget()
return widget;
}
-bool MakeStep::buildsTarget(const QString &target) const
-{
- return m_buildTargetsAspect->value().contains(target);
-}
-
-void MakeStep::setBuildTarget(const QString &target, bool on)
-{
- QStringList old = m_buildTargetsAspect->value();
- if (on && !old.contains(target))
- old << target;
- else if (!on && old.contains(target))
- old.removeOne(target);
-
- m_buildTargetsAspect->setValue(old);
-}
-
QStringList MakeStep::availableTargets() const
{
return m_buildTargetsAspect->allValues();
diff --git a/src/plugins/projectexplorer/makestep.h b/src/plugins/projectexplorer/makestep.h
index b08462db2f..2f12894ea6 100644
--- a/src/plugins/projectexplorer/makestep.h
+++ b/src/plugins/projectexplorer/makestep.h
@@ -55,11 +55,6 @@ public:
Utils::Environment makeEnvironment() const;
- // FIXME: All unused, remove in 4.15.
- void setBuildTarget(const QString &buildTarget) { setSelectedBuildTarget(buildTarget); }
- bool buildsTarget(const QString &target) const;
- void setBuildTarget(const QString &target, bool on);
-
protected:
void supportDisablingForSubdirs() { m_disablingForSubDirsSupported = true; }
virtual QStringList displayArguments() const;
@@ -78,7 +73,6 @@ private:
QStringList jobArguments() const;
Utils::MultiSelectionAspect *m_buildTargetsAspect = nullptr;
- QStringList m_availableTargets; // FIXME: Unused, remove in 4.15.
Utils::StringAspect *m_makeCommandAspect = nullptr;
Utils::StringAspect *m_userArgumentsAspect = nullptr;
Utils::IntegerAspect *m_userJobCountAspect = nullptr;
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index b169697cd8..3a1b01b724 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -13,8 +13,8 @@
#include "projectexplorerconstants.h"
#include "projectexplorericons.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "runconfiguration.h"
-#include "session.h"
#include "target.h"
#include <utils/algorithm.h>
@@ -32,6 +32,7 @@
#include <coreplugin/modemanager.h>
#include <QAction>
+#include <QCollator>
#include <QGuiApplication>
#include <QItemDelegate>
#include <QKeyEvent>
@@ -141,8 +142,15 @@ private:
static bool compareItems(const TreeItem *ti1, const TreeItem *ti2)
{
- const int result = caseFriendlyCompare(static_cast<const GenericItem *>(ti1)->rawDisplayName(),
- static_cast<const GenericItem *>(ti2)->rawDisplayName());
+ static const QCollator collator = [] {
+ QCollator collator;
+ collator.setNumericMode(true);
+ collator.setCaseSensitivity(Qt::CaseInsensitive);
+ return collator;
+ }();
+
+ const int result = collator.compare(static_cast<const GenericItem *>(ti1)->rawDisplayName(),
+ static_cast<const GenericItem *>(ti2)->rawDisplayName());
if (result != 0)
return result < 0;
return ti1 < ti2;
@@ -253,9 +261,9 @@ public:
explicit ProjectListView(QWidget *parent = nullptr) : SelectorView(parent)
{
const auto model = new GenericModel(this);
- model->rebuild(transform<QList<QObject *>>(SessionManager::projects(),
+ model->rebuild(transform<QList<QObject *>>(ProjectManager::projects(),
[](Project *p) { return p; }));
- connect(SessionManager::instance(), &SessionManager::projectAdded,
+ connect(ProjectManager::instance(), &ProjectManager::projectAdded,
this, [this, model](Project *project) {
const GenericItem *projectItem = model->addItemForObject(project);
QFontMetrics fn(font());
@@ -264,7 +272,7 @@ public:
setOptimalWidth(width);
restoreCurrentIndex();
});
- connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject,
+ connect(ProjectManager::instance(), &ProjectManager::aboutToRemoveProject,
this, [this, model](const Project *project) {
GenericItem * const item = model->itemForObject(project);
if (!item)
@@ -272,7 +280,7 @@ public:
model->destroyItem(item);
resetOptimalWidth();
});
- connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
+ connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged,
this, [this, model](const Project *project) {
const GenericItem * const item = model->itemForObject(project);
if (item)
@@ -288,7 +296,7 @@ public:
this, [model](const QModelIndex &index) {
const GenericItem * const item = model->itemForIndex(index);
if (item && item->object())
- SessionManager::setStartupProject(qobject_cast<Project *>(item->object()));
+ ProjectManager::setStartupProject(qobject_cast<Project *>(item->object()));
});
}
@@ -296,7 +304,7 @@ private:
void restoreCurrentIndex()
{
const GenericItem * const itemForStartupProject
- = theModel()->itemForObject(SessionManager::startupProject());
+ = theModel()->itemForObject(ProjectManager::startupProject());
if (itemForStartupProject)
setCurrentIndex(theModel()->indexForItem(itemForStartupProject));
}
@@ -389,6 +397,12 @@ private:
TreeView::mouseReleaseEvent(event);
}
+ void showEvent(QShowEvent* event) override
+ {
+ scrollTo(currentIndex());
+ TreeView::showEvent(event);
+ }
+
QObject *objectAt(const QModelIndex &index) const
{
return theModel()->itemForIndex(index)->object();
@@ -551,6 +565,11 @@ int SelectorView::padding()
/////////
// KitAreaWidget
/////////
+void doLayout(KitAspectWidget *widget, Layouting::LayoutItem &builder)
+{
+ widget->addToLayout(builder);
+}
+
class KitAreaWidget : public QWidget
{
Q_OBJECT
@@ -573,18 +592,15 @@ public:
delete layout();
- Layouting::LayoutBuilder builder(Layouting::LayoutBuilder::GridLayout);
+ Layouting::Grid grid;
for (KitAspect *aspect : KitManager::kitAspects()) {
if (k && k->isMutable(aspect->id())) {
KitAspectWidget *widget = aspect->createConfigWidget(k);
m_widgets << widget;
- QLabel *label = new QLabel(aspect->displayName());
- builder.addItem(label);
- widget->addToLayout(builder);
- builder.finishRow();
+ grid.addItems({aspect->displayName(), widget, Layouting::br});
}
}
- builder.attachTo(this);
+ grid.attachTo(this);
layout()->setContentsMargins(3, 3, 3, 3);
m_kit = k;
@@ -653,7 +669,7 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
QWidget(parent),
m_projectAction(targetSelectorAction)
{
- setProperty("panelwidget", true);
+ StyleHelper::setPanelWidget(this);
setContentsMargins(QMargins(0, 1, 1, 8));
setWindowFlags(Qt::Popup);
@@ -696,22 +712,22 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
m_listWidgets[RUN]->viewport()->setAttribute(Qt::WA_Hover);
// Validate state: At this point the session is still empty!
- Project *startup = SessionManager::startupProject();
+ Project *startup = ProjectManager::startupProject();
QTC_CHECK(!startup);
- QTC_CHECK(SessionManager::projects().isEmpty());
+ QTC_CHECK(ProjectManager::projects().isEmpty());
connect(m_summaryLabel, &QLabel::linkActivated,
this, &MiniProjectTargetSelector::switchToProjectsMode);
- SessionManager *sessionManager = SessionManager::instance();
- connect(sessionManager, &SessionManager::startupProjectChanged,
+ ProjectManager *sessionManager = ProjectManager::instance();
+ connect(sessionManager, &ProjectManager::startupProjectChanged,
this, &MiniProjectTargetSelector::changeStartupProject);
- connect(sessionManager, &SessionManager::projectAdded,
+ connect(sessionManager, &ProjectManager::projectAdded,
this, &MiniProjectTargetSelector::projectAdded);
- connect(sessionManager, &SessionManager::projectRemoved,
+ connect(sessionManager, &ProjectManager::projectRemoved,
this, &MiniProjectTargetSelector::projectRemoved);
- connect(sessionManager, &SessionManager::projectDisplayNameChanged,
+ connect(sessionManager, &ProjectManager::projectDisplayNameChanged,
this, &MiniProjectTargetSelector::updateActionAndSummary);
// for icon changes:
@@ -720,17 +736,17 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
connect(m_listWidgets[TARGET], &GenericListWidget::changeActiveProjectConfiguration,
this, [this](QObject *pc) {
- SessionManager::setActiveTarget(m_project, static_cast<Target *>(pc), SetActive::Cascade);
+ m_project->setActiveTarget(static_cast<Target *>(pc), SetActive::Cascade);
});
connect(m_listWidgets[BUILD], &GenericListWidget::changeActiveProjectConfiguration,
this, [this](QObject *pc) {
- SessionManager::setActiveBuildConfiguration(m_project->activeTarget(),
- static_cast<BuildConfiguration *>(pc), SetActive::Cascade);
+ m_project->activeTarget()->setActiveBuildConfiguration(
+ static_cast<BuildConfiguration *>(pc), SetActive::Cascade);
});
connect(m_listWidgets[DEPLOY], &GenericListWidget::changeActiveProjectConfiguration,
this, [this](QObject *pc) {
- SessionManager::setActiveDeployConfiguration(m_project->activeTarget(),
- static_cast<DeployConfiguration *>(pc), SetActive::Cascade);
+ m_project->activeTarget()->setActiveDeployConfiguration(
+ static_cast<DeployConfiguration *>(pc), SetActive::Cascade);
});
connect(m_listWidgets[RUN], &GenericListWidget::changeActiveProjectConfiguration,
this, [this](QObject *pc) {
@@ -881,7 +897,7 @@ void MiniProjectTargetSelector::doLayout(bool keepSize)
onlySummary = true;
} else {
if (visibleLineCount < 3) {
- if (Utils::anyOf(SessionManager::projects(), &Project::needsConfiguration))
+ if (Utils::anyOf(ProjectManager::projects(), &Project::needsConfiguration))
visibleLineCount = 3;
}
if (visibleLineCount)
@@ -1126,7 +1142,7 @@ void MiniProjectTargetSelector::removedRunConfiguration(RunConfiguration *rc, bo
void MiniProjectTargetSelector::updateProjectListVisible()
{
- int count = SessionManager::projects().size();
+ int count = ProjectManager::projects().size();
bool visible = count > 1;
m_projectListWidget->setVisible(visible);
@@ -1139,7 +1155,7 @@ void MiniProjectTargetSelector::updateProjectListVisible()
void MiniProjectTargetSelector::updateTargetListVisible()
{
int maxCount = 0;
- for (Project *p : SessionManager::projects())
+ for (Project *p : ProjectManager::projects())
maxCount = qMax(p->targets().size(), maxCount);
bool visible = maxCount > 1;
@@ -1152,7 +1168,7 @@ void MiniProjectTargetSelector::updateTargetListVisible()
void MiniProjectTargetSelector::updateBuildListVisible()
{
int maxCount = 0;
- for (Project *p : SessionManager::projects()) {
+ for (Project *p : ProjectManager::projects()) {
const QList<Target *> targets = p->targets();
for (Target *t : targets)
maxCount = qMax(t->buildConfigurations().size(), maxCount);
@@ -1168,7 +1184,7 @@ void MiniProjectTargetSelector::updateBuildListVisible()
void MiniProjectTargetSelector::updateDeployListVisible()
{
int maxCount = 0;
- for (Project *p : SessionManager::projects()) {
+ for (Project *p : ProjectManager::projects()) {
const QList<Target *> targets = p->targets();
for (Target *t : targets)
maxCount = qMax(t->deployConfigurations().size(), maxCount);
@@ -1184,7 +1200,7 @@ void MiniProjectTargetSelector::updateDeployListVisible()
void MiniProjectTargetSelector::updateRunListVisible()
{
int maxCount = 0;
- for (Project *p : SessionManager::projects()) {
+ for (Project *p : ProjectManager::projects()) {
const QList<Target *> targets = p->targets();
for (Target *t : targets)
maxCount = qMax(t->runConfigurations().size(), maxCount);
@@ -1460,10 +1476,10 @@ void MiniProjectTargetSelector::updateActionAndSummary()
? Icons::DESKTOP_DEVICE.icon()
: style()->standardIcon(QStyle::SP_ComputerIcon);
- Project *project = SessionManager::startupProject();
+ Project *project = ProjectManager::startupProject();
if (project) {
projectName = project->displayName();
- for (Project *p : SessionManager::projects()) {
+ for (Project *p : ProjectManager::projects()) {
if (p != project && p->displayName() == projectName) {
fileName = project->projectFilePath().toUserOutput();
break;
@@ -1515,7 +1531,7 @@ void MiniProjectTargetSelector::updateActionAndSummary()
void MiniProjectTargetSelector::updateSummary()
{
QString summary;
- if (Project *startupProject = SessionManager::startupProject()) {
+ if (Project *startupProject = ProjectManager::startupProject()) {
if (!m_projectListWidget->isVisibleTo(this))
summary.append(Tr::tr("Project: <b>%1</b><br/>").arg(startupProject->displayName()));
if (Target *activeTarget = startupProject->activeTarget()) {
diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp
index 89c59443e1..8452afcc5a 100644
--- a/src/plugins/projectexplorer/msvcparser.cpp
+++ b/src/plugins/projectexplorer/msvcparser.cpp
@@ -61,7 +61,7 @@ static Task handleNmakeJomMessage(const QString &line)
CompileTask task(type, line.mid(matchLength).trimmed());
task.details << line;
- return std::move(task);
+ return task;
}
static Task::TaskType taskType(const QString &category)
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index d0856e29d4..d4d518de44 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -3,6 +3,7 @@
#include "msvctoolchain.h"
+#include "devicesupport/idevice.h"
#include "gcctoolchain.h"
#include "msvcparser.h"
#include "projectexplorer.h"
@@ -14,12 +15,12 @@
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
+#include <utils/async.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-#include <utils/runextensions.h>
#include <utils/temporarydirectory.h>
#include <utils/winutils.h>
@@ -254,7 +255,7 @@ static std::optional<VisualStudioInstallation> detectCppBuildTools2017()
static QVector<VisualStudioInstallation> detectVisualStudioFromVsWhere(const QString &vswhere)
{
QVector<VisualStudioInstallation> installations;
- QtcProcess vsWhereProcess;
+ Process vsWhereProcess;
vsWhereProcess.setCodec(QTextCodec::codecForName("UTF-8"));
const int timeoutS = 5;
vsWhereProcess.setTimeoutS(timeoutS);
@@ -648,7 +649,7 @@ Macros MsvcToolChain::msvcPredefinedMacros(const QStringList &cxxflags,
qWarning("%s: %s", Q_FUNC_INFO, qPrintable(saver.errorString()));
return predefinedMacros;
}
- Utils::QtcProcess cpp;
+ Utils::Process cpp;
cpp.setEnvironment(env);
cpp.setWorkingDirectory(Utils::TemporaryDirectory::masterDirectoryFilePath());
QStringList arguments;
@@ -747,10 +748,8 @@ static QString winExpandDelayedEnvReferences(QString in, const Utils::Environmen
return in;
}
-void MsvcToolChain::environmentModifications(
- QFutureInterface<MsvcToolChain::GenerateEnvResult> &future,
- QString vcvarsBat,
- QString varsBatArg)
+void MsvcToolChain::environmentModifications(QPromise<MsvcToolChain::GenerateEnvResult> &promise,
+ QString vcvarsBat, QString varsBatArg)
{
const Utils::Environment inEnv = Utils::Environment::systemEnvironment();
Utils::Environment outEnv;
@@ -776,7 +775,7 @@ void MsvcToolChain::environmentModifications(
}
}
- future.reportResult({error, diff});
+ promise.addResult(MsvcToolChain::GenerateEnvResult{error, diff});
}
void MsvcToolChain::initEnvModWatcher(const QFuture<GenerateEnvResult> &future)
@@ -1004,10 +1003,8 @@ bool MsvcToolChain::fromMap(const QVariantMap &data)
data.value(QLatin1String(environModsKeyC)).toList());
rescanForCompiler();
- initEnvModWatcher(Utils::runAsync(envModThreadPool(),
- &MsvcToolChain::environmentModifications,
- m_vcvarsBat,
- m_varsBatArg));
+ initEnvModWatcher(Utils::asyncRun(envModThreadPool(), &MsvcToolChain::environmentModifications,
+ m_vcvarsBat, m_varsBatArg));
const bool valid = !m_vcvarsBat.isEmpty() && targetAbi().isValid();
if (!valid)
@@ -1128,8 +1125,8 @@ WarningFlags MsvcToolChain::warningFlags(const QStringList &cflags) const
return flags;
}
-QStringList MsvcToolChain::includedFiles(const QStringList &flags,
- const QString &directoryPath) const
+FilePaths MsvcToolChain::includedFiles(const QStringList &flags,
+ const FilePath &directoryPath) const
{
return ToolChain::includedFiles("/FI", flags, directoryPath, PossiblyConcatenatedFlag::Yes);
}
@@ -1236,10 +1233,8 @@ void MsvcToolChain::setupVarsBat(const Abi &abi, const QString &varsBat, const Q
m_varsBatArg = varsBatArg;
if (!varsBat.isEmpty()) {
- initEnvModWatcher(Utils::runAsync(envModThreadPool(),
- &MsvcToolChain::environmentModifications,
- varsBat,
- varsBatArg));
+ initEnvModWatcher(Utils::asyncRun(envModThreadPool(),
+ &MsvcToolChain::environmentModifications, varsBat, varsBatArg));
}
}
@@ -1560,7 +1555,7 @@ static QVersionNumber clangClVersion(const FilePath &clangClPath)
if (!dllversion.isEmpty())
return QVersionNumber::fromString(dllversion);
- QtcProcess clangClProcess;
+ Process clangClProcess;
clangClProcess.setCommand({clangClPath, {"--version"}});
clangClProcess.runBlocking();
if (clangClProcess.result() != ProcessResult::FinishedWithSuccess)
@@ -1777,7 +1772,7 @@ Macros ClangClToolChain::msvcPredefinedMacros(const QStringList &cxxflags,
if (!cxxflags.contains("--driver-mode=g++"))
return MsvcToolChain::msvcPredefinedMacros(cxxflags, env);
- QtcProcess cpp;
+ Process cpp;
cpp.setEnvironment(env);
cpp.setWorkingDirectory(Utils::TemporaryDirectory::masterDirectoryFilePath());
@@ -1915,7 +1910,7 @@ static void detectCppBuildTools2015(Toolchains *list)
Toolchains MsvcToolChainFactory::autoDetect(const ToolchainDetector &detector) const
{
- if (!detector.device.isNull()) {
+ if (detector.device->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
// FIXME currently no support for msvc toolchains on a device
return {};
}
@@ -2030,7 +2025,7 @@ bool ClangClToolChainFactory::canCreate() const
Toolchains ClangClToolChainFactory::autoDetect(const ToolchainDetector &detector) const
{
- if (!detector.device.isNull()) {
+ if (detector.device->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
// FIXME currently no support for msvc toolchains on a device
return {};
}
@@ -2127,7 +2122,7 @@ std::optional<QString> MsvcToolChain::generateEnvironmentSettings(const Utils::E
return QString();
}
- Utils::QtcProcess run;
+ Utils::Process run;
// As of WinSDK 7.1, there is logic preventing the path from being set
// correctly if "ORIGINALPATH" is already set. That can cause problems
diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h
index 042bbfe38f..68f8b9dcf1 100644
--- a/src/plugins/projectexplorer/msvctoolchain.h
+++ b/src/plugins/projectexplorer/msvctoolchain.h
@@ -55,8 +55,8 @@ public:
MacroInspectionRunner createMacroInspectionRunner() const override;
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
Utils::WarningFlags warningFlags(const QStringList &cflags) const override;
- QStringList includedFiles(const QStringList &flags,
- const QString &directoryPath) const override;
+ Utils::FilePaths includedFiles(const QStringList &flags,
+ const Utils::FilePath &directoryPath) const override;
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(
const Utils::Environment &env) const override;
void addToEnvironment(Utils::Environment &env) const override;
@@ -81,6 +81,8 @@ public:
const QString &batchFile,
const QString &batchArgs,
QMap<QString, QString> &envPairs);
+ bool environmentInitialized() const { return !m_environmentModifications.isEmpty(); }
+
protected:
class WarningFlagAdder
{
@@ -111,9 +113,8 @@ protected:
std::optional<QString> error;
Utils::EnvironmentItems environmentItems;
};
- static void environmentModifications(QFutureInterface<GenerateEnvResult> &future,
- QString vcvarsBat,
- QString varsBatArg);
+ static void environmentModifications(QPromise<GenerateEnvResult> &future,
+ QString vcvarsBat, QString varsBatArg);
void initEnvModWatcher(const QFuture<GenerateEnvResult> &future);
protected:
diff --git a/src/plugins/projectexplorer/processparameters.cpp b/src/plugins/projectexplorer/processparameters.cpp
index 49b50dccb3..0b3d6d83c7 100644
--- a/src/plugins/projectexplorer/processparameters.cpp
+++ b/src/plugins/projectexplorer/processparameters.cpp
@@ -5,7 +5,7 @@
#include <utils/fileutils.h>
#include <utils/macroexpander.h>
-#include <utils/qtcprocess.h>
+#include <utils/process.h>
#include <utils/theme/theme.h>
#include <utils/utilstr.h>
diff --git a/src/plugins/projectexplorer/processstep.cpp b/src/plugins/projectexplorer/processstep.cpp
index 3ced1622d0..a34ff10b61 100644
--- a/src/plugins/projectexplorer/processstep.cpp
+++ b/src/plugins/projectexplorer/processstep.cpp
@@ -34,9 +34,8 @@ public:
ProcessStep::ProcessStep(BuildStepList *bsl, Id id)
: AbstractProcessStep(bsl, id)
{
- auto command = addAspect<StringAspect>();
+ auto command = addAspect<FilePathAspect>();
command->setSettingsKey(PROCESS_COMMAND_KEY);
- command->setDisplayStyle(StringAspect::PathChooserDisplay);
command->setLabelText(Tr::tr("Command:"));
command->setExpectedKind(PathChooser::Command);
command->setHistoryCompleter("PE.ProcessStepCommand.History");
@@ -46,10 +45,9 @@ ProcessStep::ProcessStep(BuildStepList *bsl, Id id)
arguments->setDisplayStyle(StringAspect::LineEditDisplay);
arguments->setLabelText(Tr::tr("Arguments:"));
- auto workingDirectory = addAspect<StringAspect>();
+ auto workingDirectory = addAspect<FilePathAspect>();
workingDirectory->setSettingsKey(PROCESS_WORKINGDIRECTORY_KEY);
workingDirectory->setValue(Constants::DEFAULT_WORKING_DIR);
- workingDirectory->setDisplayStyle(StringAspect::PathChooserDisplay);
workingDirectory->setLabelText(Tr::tr("Working directory:"));
workingDirectory->setExpectedKind(PathChooser::Directory);
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index fbd4f9e28f..c021d9b1a6 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -11,15 +11,17 @@
#include "environmentaspect.h"
#include "kit.h"
#include "kitinformation.h"
+#include "msvctoolchain.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projectnodes.h"
#include "runconfiguration.h"
#include "runconfigurationaspects.h"
-#include "session.h"
#include "target.h"
#include "taskhub.h"
+#include "toolchainmanager.h"
#include "userfileaccessor.h"
#include <coreplugin/idocument.h>
@@ -273,7 +275,7 @@ void Project::addTarget(std::unique_ptr<Target> &&t)
// check activeTarget:
if (!activeTarget())
- SessionManager::setActiveTarget(this, pointer, SetActive::Cascade);
+ setActiveTarget(pointer, SetActive::Cascade);
}
Target *Project::addTargetForDefaultKit()
@@ -309,7 +311,7 @@ bool Project::removeTarget(Target *target)
auto keep = take(d->m_targets, target);
if (target == d->m_activeTarget) {
Target *newActiveTarget = (d->m_targets.size() == 0 ? nullptr : d->m_targets.at(0).get());
- SessionManager::setActiveTarget(this, newActiveTarget, SetActive::Cascade);
+ setActiveTarget(newActiveTarget, SetActive::Cascade);
}
emit removedTarget(target);
@@ -326,7 +328,7 @@ Target *Project::activeTarget() const
return d->m_activeTarget;
}
-void Project::setActiveTarget(Target *target)
+void Project::setActiveTargetHelper(Target *target)
{
if (d->m_activeTarget == target)
return;
@@ -414,6 +416,29 @@ Target *Project::target(Kit *k) const
return findOrDefault(d->m_targets, equal(&Target::kit, k));
}
+void Project::setActiveTarget(Target *target, SetActive cascade)
+{
+ if (isShuttingDown())
+ return;
+
+ setActiveTargetHelper(target);
+
+ if (!target) // never cascade setting no target
+ return;
+
+ if (cascade != SetActive::Cascade || !ProjectManager::isProjectConfigurationCascading())
+ return;
+
+ Utils::Id kitId = target->kit()->id();
+ for (Project *otherProject : ProjectManager::projects()) {
+ if (otherProject == this)
+ continue;
+ if (Target *otherTarget = Utils::findOrDefault(otherProject->targets(),
+ [kitId](Target *t) { return t->kit()->id() == kitId; }))
+ otherProject->setActiveTargetHelper(otherTarget);
+ }
+}
+
Tasks Project::projectIssues(const Kit *k) const
{
Tasks result;
@@ -445,12 +470,12 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
sourceBc->buildSystem()->name()));
newTarget->addBuildConfiguration(newBc);
if (sourceTarget->activeBuildConfiguration() == sourceBc)
- SessionManager::setActiveBuildConfiguration(newTarget, newBc, SetActive::NoCascade);
+ newTarget->setActiveBuildConfiguration(newBc, SetActive::NoCascade);
}
if (!newTarget->activeBuildConfiguration()) {
QList<BuildConfiguration *> bcs = newTarget->buildConfigurations();
if (!bcs.isEmpty())
- SessionManager::setActiveBuildConfiguration(newTarget, bcs.first(), SetActive::NoCascade);
+ newTarget->setActiveBuildConfiguration(bcs.first(), SetActive::NoCascade);
}
for (DeployConfiguration *sourceDc : sourceTarget->deployConfigurations()) {
@@ -462,12 +487,12 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
newDc->setDisplayName(sourceDc->displayName());
newTarget->addDeployConfiguration(newDc);
if (sourceTarget->activeDeployConfiguration() == sourceDc)
- SessionManager::setActiveDeployConfiguration(newTarget, newDc, SetActive::NoCascade);
+ newTarget->setActiveDeployConfiguration(newDc, SetActive::NoCascade);
}
if (!newTarget->activeBuildConfiguration()) {
QList<DeployConfiguration *> dcs = newTarget->deployConfigurations();
if (!dcs.isEmpty())
- SessionManager::setActiveDeployConfiguration(newTarget, dcs.first(), SetActive::NoCascade);
+ newTarget->setActiveDeployConfiguration(dcs.first(), SetActive::NoCascade);
}
for (RunConfiguration *sourceRc : sourceTarget->runConfigurations()) {
@@ -846,6 +871,34 @@ const Node *Project::nodeForFilePath(const FilePath &filePath,
return nullptr;
}
+FilePaths Project::binariesForSourceFile(const FilePath &sourceFile) const
+{
+ if (!rootProjectNode())
+ return {};
+ const QList<Node *> fileNodes = rootProjectNode()->findNodes([&sourceFile](Node *n) {
+ return n->filePath() == sourceFile;
+ });
+ FilePaths binaries;
+ for (const Node * const fileNode : fileNodes) {
+ for (ProjectNode *projectNode = fileNode->parentProjectNode(); projectNode;
+ projectNode = projectNode->parentProjectNode()) {
+ if (!projectNode->isProduct())
+ continue;
+ if (projectNode->productType() == ProductType::App
+ || projectNode->productType() == ProductType::Lib) {
+ const QList<Node *> binaryNodes = projectNode->findNodes([](Node *n) {
+ return n->asFileNode() && (n->asFileNode()->fileType() == FileType::App
+ || n->asFileNode()->fileType() == FileType::Lib);
+
+ });
+ binaries << Utils::transform(binaryNodes, &Node::filePath);
+ }
+ break;
+ }
+ }
+ return binaries;
+}
+
void Project::setProjectLanguages(Context language)
{
if (d->m_projectLanguages == language)
@@ -1130,7 +1183,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
});
expander->registerVariable(fullPrefix + "Kit:Name",
//: %1 is something like "Active project"
- Tr::tr("%1: The name the active kit.").arg(descriptor),
+ Tr::tr("%1: The name of the active kit.").arg(descriptor),
[targetGetter]() -> QString {
if (const Target *const target = targetGetter())
return target->kit()->displayName();
@@ -1435,8 +1488,7 @@ void ProjectExplorerPlugin::testProject_multipleBuildConfigs()
Target * const target = theProject.project()->activeTarget();
QVERIFY(target);
QCOMPARE(target->buildConfigurations().size(), 6);
- SessionManager::setActiveBuildConfiguration(target, target->buildConfigurations().at(1),
- SetActive::Cascade);
+ target->setActiveBuildConfiguration(target->buildConfigurations().at(1), SetActive::Cascade);
BuildSystem * const bs = theProject.project()->activeTarget()->buildSystem();
QVERIFY(bs);
QCOMPARE(bs, target->activeBuildConfiguration()->buildSystem());
@@ -1452,12 +1504,94 @@ void ProjectExplorerPlugin::testProject_multipleBuildConfigs()
}
QVERIFY(!bs->isWaitingForParse() && !bs->isParsing());
- QCOMPARE(SessionManager::startupProject(), theProject.project());
+ QCOMPARE(ProjectManager::startupProject(), theProject.project());
QCOMPARE(ProjectTree::currentProject(), theProject.project());
QVERIFY(EditorManager::openEditor(projectDir.pathAppended("main.cpp")));
QVERIFY(ProjectTree::currentNode());
ProjectTree::instance()->expandAll();
- SessionManager::closeAllProjects(); // QTCREATORBUG-25655
+ ProjectManager::closeAllProjects(); // QTCREATORBUG-25655
+}
+
+void ProjectExplorerPlugin::testSourceToBinaryMapping()
+{
+ // Find suitable kit.
+ Kit * const kit = findOr(KitManager::kits(), nullptr, [](const Kit *k) {
+ return k->isValid() && ToolChainKitAspect::cxxToolChain(k);
+ });
+ if (!kit)
+ QSKIP("The test requires at least one kit with a toolchain.");
+
+ const auto toolchain = ToolChainKitAspect::cxxToolChain(kit);
+ QVERIFY(toolchain);
+ if (const auto msvcToolchain = dynamic_cast<Internal::MsvcToolChain *>(toolchain)) {
+ while (!msvcToolchain->environmentInitialized()) {
+ QSignalSpy parsingFinishedSpy(ToolChainManager::instance(),
+ &ToolChainManager::toolChainUpdated);
+ QVERIFY(parsingFinishedSpy.wait(10000));
+ }
+ }
+
+ // Copy project from qrc.
+ QTemporaryDir * const tempDir = TemporaryDirectory::masterTemporaryDirectory();
+ QVERIFY(tempDir->isValid());
+ const FilePath projectDir = FilePath::fromString(tempDir->path() + "/multi-target-project");
+ if (!projectDir.exists()) {
+ const auto result = FilePath(":/projectexplorer/testdata/multi-target-project")
+ .copyRecursively(projectDir);
+ QVERIFY2(result, qPrintable(result.error()));
+ const QFileInfoList files = QDir(projectDir.toString()).entryInfoList(QDir::Files);
+ for (const QFileInfo &f : files)
+ QFile(f.absoluteFilePath()).setPermissions(f.permissions() | QFile::WriteUser);
+ }
+
+ // Load Project.
+ QFETCH(QString, projectFileName);
+ const auto theProject = openProject(projectDir.pathAppended(projectFileName));
+ if (theProject.errorMessage().contains("text/")) {
+ QSKIP("This test requires the presence of the qmake/cmake/qbs project managers "
+ "to be fully functional");
+ }
+
+ QVERIFY2(theProject, qPrintable(theProject.errorMessage()));
+ theProject.project()->configureAsExampleProject(kit);
+ QCOMPARE(theProject.project()->targets().size(), 1);
+ Target * const target = theProject.project()->activeTarget();
+ QVERIFY(target);
+ BuildSystem * const bs = target->buildSystem();
+ QVERIFY(bs);
+ QCOMPARE(bs, target->activeBuildConfiguration()->buildSystem());
+ if (bs->isWaitingForParse() || bs->isParsing()) {
+ QSignalSpy parsingFinishedSpy(bs, &BuildSystem::parsingFinished);
+ QVERIFY(parsingFinishedSpy.wait(10000));
+ }
+ QVERIFY(!bs->isWaitingForParse() && !bs->isParsing());
+
+ if (QLatin1String(QTest::currentDataTag()) == QLatin1String("qbs")) {
+ BuildManager::buildProjectWithoutDependencies(theProject.project());
+ if (BuildManager::isBuilding()) {
+ QSignalSpy buildingFinishedSpy(BuildManager::instance(), &BuildManager::buildQueueFinished);
+ QVERIFY(buildingFinishedSpy.wait(10000));
+ }
+ QVERIFY(!BuildManager::isBuilding());
+ QSignalSpy projectUpdateSpy(theProject.project(), &Project::fileListChanged);
+ QVERIFY(projectUpdateSpy.wait(5000));
+ }
+
+ // Check mapping
+ const auto binariesForSource = [&](const QString &fileName) {
+ return theProject.project()->binariesForSourceFile(projectDir.pathAppended(fileName));
+ };
+ QCOMPARE(binariesForSource("multi-target-project-main.cpp").size(), 1);
+ QCOMPARE(binariesForSource("multi-target-project-lib.cpp").size(), 1);
+ QCOMPARE(binariesForSource("multi-target-project-shared.h").size(), 2);
+}
+
+void ProjectExplorerPlugin::testSourceToBinaryMapping_data()
+{
+ QTest::addColumn<QString>("projectFileName");
+ QTest::addRow("cmake") << "CMakeLists.txt";
+ QTest::addRow("qbs") << "multi-target-project.qbs";
+ QTest::addRow("qmake") << "multi-target-project.pro";
}
#endif // WITH_TESTS
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index ed336b5f7f..832fc3c942 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -36,11 +36,11 @@ class ProjectImporter;
class ProjectNode;
class ProjectPrivate;
class Target;
+enum class SetActive : int;
// Documentation inside.
class PROJECTEXPLORER_EXPORT Project : public QObject
{
- friend class SessionManager; // for setActiveTarget
Q_OBJECT
public:
@@ -89,6 +89,8 @@ public:
Target *activeTarget() const;
Target *target(Utils::Id id) const;
Target *target(Kit *k) const;
+ void setActiveTarget(Target *target, SetActive cascade);
+
virtual Tasks projectIssues(const Kit *k) const;
static bool copySteps(Target *sourceTarget, Target *newTarget);
@@ -107,6 +109,7 @@ public:
bool isKnownFile(const Utils::FilePath &filename) const;
const Node *nodeForFilePath(const Utils::FilePath &filePath,
const NodeMatcher &extraMatcher = {}) const;
+ Utils::FilePaths binariesForSourceFile(const Utils::FilePath &sourceFile) const;
virtual QVariantMap toMap() const;
@@ -226,7 +229,7 @@ private:
void removeProjectLanguage(Utils::Id id);
void handleSubTreeChanged(FolderNode *node);
- void setActiveTarget(Target *target);
+ void setActiveTargetHelper(Target *target);
friend class ContainerNode;
ProjectPrivate *d;
diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp
index 6d5fa797a6..841be31731 100644
--- a/src/plugins/projectexplorer/projectconfiguration.cpp
+++ b/src/plugins/projectexplorer/projectconfiguration.cpp
@@ -19,11 +19,9 @@ const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DisplayNam
// ProjectConfiguration
ProjectConfiguration::ProjectConfiguration(QObject *parent, Utils::Id id)
- : QObject(parent)
+ : AspectContainer(parent)
, m_id(id)
{
- m_aspects.setOwnsSubAspects(true);
-
QTC_CHECK(parent);
QTC_CHECK(id.isValid());
setObjectName(id.toString());
@@ -89,7 +87,7 @@ QVariantMap ProjectConfiguration::toMap() const
QVariantMap map;
map.insert(QLatin1String(CONFIGURATION_ID_KEY), m_id.toSetting());
m_displayName.toMap(map, DISPLAY_NAME_KEY);
- m_aspects.toMap(map);
+ AspectContainer::toMap(map);
return map;
}
@@ -106,15 +104,10 @@ bool ProjectConfiguration::fromMap(const QVariantMap &map)
QTC_ASSERT(id.toString().startsWith(m_id.toString()), return false);
m_displayName.fromMap(map, DISPLAY_NAME_KEY);
- m_aspects.fromMap(map);
+ AspectContainer::fromMap(map);
return true;
}
-BaseAspect *ProjectConfiguration::aspect(Id id) const
-{
- return m_aspects.aspect(id);
-}
-
FilePath ProjectConfiguration::mapFromBuildDeviceToGlobalPath(const FilePath &path) const
{
IDevice::ConstPtr dev = BuildDeviceKitAspect::device(kit());
diff --git a/src/plugins/projectexplorer/projectconfiguration.h b/src/plugins/projectexplorer/projectconfiguration.h
index cb716bf66e..8c5dac1d90 100644
--- a/src/plugins/projectexplorer/projectconfiguration.h
+++ b/src/plugins/projectexplorer/projectconfiguration.h
@@ -21,7 +21,7 @@ class Kit;
class Project;
class Target;
-class PROJECTEXPLORER_EXPORT ProjectConfiguration : public QObject
+class PROJECTEXPLORER_EXPORT ProjectConfiguration : public Utils::AspectContainer
{
Q_OBJECT
@@ -54,26 +54,12 @@ public:
static QString settingsIdKey();
- template<class Aspect, typename ...Args>
- Aspect *addAspect(Args && ...args)
- {
- return m_aspects.addAspect<Aspect>(std::forward<Args>(args)...);
- }
-
- const Utils::AspectContainer &aspects() const { return m_aspects; }
-
- Utils::BaseAspect *aspect(Utils::Id id) const;
- template <typename T> T *aspect() const { return m_aspects.aspect<T>(); }
-
Utils::FilePath mapFromBuildDeviceToGlobalPath(const Utils::FilePath &path) const;
signals:
void displayNameChanged();
void toolTipChanged();
-protected:
- Utils::AspectContainer m_aspects;
-
private:
QPointer<Target> m_target;
const Utils::Id m_id;
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index f76f10175b..d313cb433d 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -8,6 +8,7 @@
#include "buildsystem.h"
#include "compileoutputwindow.h"
#include "configtaskhandler.h"
+#include "copystep.h"
#include "customexecutablerunconfiguration.h"
#include "customparserssettingspage.h"
#include "customwizard/customwizard.h"
@@ -34,11 +35,13 @@
#include "dependenciespanel.h"
#include "devicesupport/desktopdevice.h"
#include "devicesupport/desktopdevicefactory.h"
+#include "devicesupport/devicecheckbuildstep.h"
#include "devicesupport/devicemanager.h"
#include "devicesupport/devicesettingspage.h"
#include "devicesupport/sshsettings.h"
#include "devicesupport/sshsettingspage.h"
#include "editorsettingspropertiespage.h"
+#include "environmentaspect.h"
#include "filesinallprojectsfind.h"
#include "jsonwizard/jsonwizardfactory.h"
#include "jsonwizard/jsonwizardgeneratorfactory.h"
@@ -54,7 +57,6 @@
#include "project.h"
#include "projectexplorericons.h"
#include "projectexplorersettings.h"
-#include "projectexplorersettingspage.h"
#include "projectexplorertr.h"
#include "projectfilewizardextension.h"
#include "projectmanager.h"
@@ -63,11 +65,8 @@
#include "projecttreewidget.h"
#include "projectwindow.h"
#include "removetaskhandler.h"
-#include "runconfigurationaspects.h"
#include "sanitizerparser.h"
#include "selectablefilesmodel.h"
-#include "session.h"
-#include "sessiondialog.h"
#include "showineditortaskhandler.h"
#include "simpleprojectwizard.h"
#include "target.h"
@@ -108,6 +107,7 @@
#include <coreplugin/modemanager.h>
#include <coreplugin/navigationwidget.h>
#include <coreplugin/outputpane.h>
+#include <coreplugin/session.h>
#include <coreplugin/vcsmanager.h>
#include <extensionsystem/pluginmanager.h>
@@ -127,6 +127,7 @@
#include <utils/qtcassert.h>
#include <utils/removefiledialog.h>
#include <utils/stringutils.h>
+#include <utils/terminalhooks.h>
#include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h>
@@ -173,6 +174,7 @@
*/
using namespace Core;
+using namespace ExtensionSystem;
using namespace ProjectExplorer::Internal;
using namespace Utils;
@@ -240,7 +242,6 @@ const int P_ACTION_BUILDPROJECT = 80;
// Menus
const char M_RECENTPROJECTS[] = "ProjectExplorer.Menu.Recent";
const char M_UNLOADPROJECTS[] = "ProjectExplorer.Menu.Unload";
-const char M_SESSION[] = "ProjectExplorer.Menu.Session";
const char M_GENERATORS[] = "ProjectExplorer.Menu.Generators";
const char RUNMENUCONTEXTMENU[] = "Project.RunMenu";
@@ -254,7 +255,6 @@ const char BUILD_BEFORE_DEPLOY_SETTINGS_KEY[] = "ProjectExplorer/Settings/BuildB
const char DEPLOY_BEFORE_RUN_SETTINGS_KEY[] = "ProjectExplorer/Settings/DeployBeforeRun";
const char SAVE_BEFORE_BUILD_SETTINGS_KEY[] = "ProjectExplorer/Settings/SaveBeforeBuild";
const char USE_JOM_SETTINGS_KEY[] = "ProjectExplorer/Settings/UseJom";
-const char AUTO_RESTORE_SESSION_SETTINGS_KEY[] = "ProjectExplorer/Settings/AutoRestoreLastSession";
const char ADD_LIBRARY_PATHS_TO_RUN_ENV_SETTINGS_KEY[] =
"ProjectExplorer/Settings/AddLibraryPathsToRunEnv";
const char PROMPT_TO_STOP_RUN_CONTROL_SETTINGS_KEY[] =
@@ -303,12 +303,12 @@ static const RunConfiguration *runConfigForNode(const Target *target, const Proj
static bool hideBuildMenu()
{
- return Core::ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_BUILD, false).toBool();
+ return ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_BUILD, false).toBool();
}
static bool hideDebugMenu()
{
- return Core::ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_DEBUG, false).toBool();
+ return ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_DEBUG, false).toBool();
}
static bool canOpenTerminalWithRunEnv(const Project *project, const ProjectNode *node)
@@ -337,7 +337,7 @@ static BuildConfiguration *currentBuildConfiguration()
static Target *activeTarget()
{
- const Project * const project = SessionManager::startupProject();
+ const Project * const project = ProjectManager::startupProject();
return project ? project->activeTarget() : nullptr;
}
@@ -405,40 +405,22 @@ protected:
void restoreState(const QJsonObject &object) override;
};
-class RunConfigurationLocatorFilter : public Core::ILocatorFilter
+class RunConfigurationStartFilter final : public ILocatorFilter
{
public:
- RunConfigurationLocatorFilter();
-
- void prepareSearch(const QString &entry) override;
- QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
- const QString &entry) override;
+ RunConfigurationStartFilter();
private:
- void targetListUpdated();
- QList<Core::LocatorFilterEntry> m_result;
-};
-
-class RunRunConfigurationLocatorFilter final : public RunConfigurationLocatorFilter
-{
-public:
- RunRunConfigurationLocatorFilter();
-
- void accept(const Core::LocatorFilterEntry &selection,
- QString *newText,
- int *selectionStart,
- int *selectionLength) const final;
+ Core::LocatorMatcherTasks matchers() final;
};
-class SwitchToRunConfigurationLocatorFilter final : public RunConfigurationLocatorFilter
+class RunConfigurationSwitchFilter final : public ILocatorFilter
{
public:
- SwitchToRunConfigurationLocatorFilter();
+ RunConfigurationSwitchFilter();
- void accept(const Core::LocatorFilterEntry &selection,
- QString *newText,
- int *selectionStart,
- int *selectionLength) const final;
+private:
+ Core::LocatorMatcherTasks matchers() final;
};
class ProjectExplorerPluginPrivate : public QObject
@@ -468,12 +450,7 @@ public:
void unloadProjectContextMenu();
void unloadOtherProjectsContextMenu();
void closeAllProjects();
- void showSessionManager();
- void updateSessionMenu();
- void setSession(QAction *action);
- void determineSessionToRestoreAtStartup();
- void restoreSession();
void runProjectContextMenu(RunConfiguration *rc);
void savePersistentSettings();
@@ -492,7 +469,7 @@ public:
void deleteFile();
void handleRenameFile();
void handleSetStartupProject();
- void setStartupProject(ProjectExplorer::Project *project);
+ void setStartupProject(Project *project);
bool closeAllFilesInProject(const Project *project);
void updateRecentProjectMenu();
@@ -504,11 +481,11 @@ public:
void openTerminalHere(const EnvironmentGetter &env);
void openTerminalHereWithRunEnv();
- void invalidateProject(ProjectExplorer::Project *project);
+ void invalidateProject(Project *project);
- void projectAdded(ProjectExplorer::Project *pro);
- void projectRemoved(ProjectExplorer::Project *pro);
- void projectDisplayNameChanged(ProjectExplorer::Project *pro);
+ void projectAdded(Project *pro);
+ void projectRemoved(Project *pro);
+ void projectDisplayNameChanged(Project *pro);
void doUpdateRunActions();
@@ -525,12 +502,10 @@ public:
void extendFolderNavigationWidgetFactory();
public:
- QMenu *m_sessionMenu;
QMenu *m_openWithMenu;
QMenu *m_openTerminalMenu;
QMultiMap<int, QObject*> m_actionMap;
- QAction *m_sessionManagerAction;
QAction *m_newAction;
QAction *m_loadAction;
ParameterAction *m_unloadAction;
@@ -599,7 +574,6 @@ public:
QAction *m_runSubProject;
ProjectWindow *m_proWindow = nullptr;
- QString m_sessionToRestoreAtStartup;
QStringList m_profileMimeTypes;
int m_activeRunControlCount = 0;
@@ -618,11 +592,9 @@ public:
BuildPropertiesSettings m_buildPropertiesSettings;
QList<CustomParserSettings> m_customParsers;
bool m_shouldHaveRunConfiguration = false;
- bool m_shuttingDown = false;
Id m_runMode = Constants::NO_RUN_MODE;
ToolChainManager *m_toolChainManager = nullptr;
- QStringList m_arguments;
#ifdef WITH_JOURNALD
JournaldWatcher m_journalWatcher;
@@ -667,7 +639,7 @@ public:
RemoveTaskHandler m_removeTaskHandler;
ConfigTaskHandler m_configTaskHandler{Task::compilerMissingTask(), Constants::KITS_SETTINGS_PAGE_ID};
- SessionManager m_sessionManager;
+ ProjectManager m_sessionManager;
AppOutputPane m_outputPane;
ProjectTree m_projectTree;
@@ -675,9 +647,11 @@ public:
AllProjectsFilter m_allProjectsFilter;
CurrentProjectFilter m_currentProjectFilter;
AllProjectFilesFilter m_allProjectDirectoriesFilter;
- RunRunConfigurationLocatorFilter m_runConfigurationLocatorFilter;
- SwitchToRunConfigurationLocatorFilter m_switchRunConfigurationLocatorFilter;
+ RunConfigurationStartFilter m_runConfigurationStartFilter;
+ RunConfigurationSwitchFilter m_runConfigurationSwitchFilter;
+ CopyFileStepFactory m_copyFileStepFactory;
+ CopyDirectoryStepFactory m_copyDirectoryFactory;
ProcessStepFactory m_processStepFactory;
AllProjectsFind m_allProjectsFind;
@@ -691,9 +665,7 @@ public:
// Settings pages
ProjectExplorerSettingsPage m_projectExplorerSettingsPage;
- BuildPropertiesSettingsPage m_buildPropertiesSettingsPage{&m_buildPropertiesSettings};
AppOutputSettingsPage m_appOutputSettingsPage;
- CompileOutputSettingsPage m_compileOutputSettingsPage;
DeviceSettingsPage m_deviceSettingsPage;
SshSettingsPage m_sshSettingsPage;
CustomParsersSettingsPage m_customParsersSettingsPage;
@@ -721,6 +693,7 @@ public:
cmakeRunConfigFactory.runConfigurationId()
}};
+ DeviceCheckBuildStepFactory deviceCheckBuildStepFactory;
SanitizerOutputFormatterFactory sanitizerFormatterFactory;
};
@@ -743,7 +716,7 @@ static void openProjectsInDirectory(const FilePath &filePath)
{
const FilePaths projectFiles = projectsInDirectory(filePath);
if (!projectFiles.isEmpty())
- Core::ICore::openFiles(projectFiles);
+ ICore::openFiles(projectFiles);
}
static QStringList projectNames(const QVector<FolderNode *> &folders)
@@ -766,7 +739,7 @@ static QVector<FolderNode *> renamableFolderNodes(const FilePath &before, const
return folderNodes;
}
-static QVector<FolderNode *> removableFolderNodes(const Utils::FilePath &filePath)
+static QVector<FolderNode *> removableFolderNodes(const FilePath &filePath)
{
QVector<FolderNode *> folderNodes;
ProjectTree::forEachNode([&](Node *node) {
@@ -831,40 +804,33 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
IWizardFactory::registerFeatureProvider(new KitFeatureProvider);
IWizardFactory::registerFactoryCreator([] { return new SimpleProjectWizard; });
- connect(&dd->m_welcomePage, &ProjectWelcomePage::manageSessions,
- dd, &ProjectExplorerPluginPrivate::showSessionManager);
-
- SessionManager *sessionManager = &dd->m_sessionManager;
- connect(sessionManager, &SessionManager::projectAdded,
+ ProjectManager *sessionManager = &dd->m_sessionManager;
+ connect(sessionManager, &ProjectManager::projectAdded,
this, &ProjectExplorerPlugin::fileListChanged);
- connect(sessionManager, &SessionManager::aboutToRemoveProject,
+ connect(sessionManager, &ProjectManager::aboutToRemoveProject,
dd, &ProjectExplorerPluginPrivate::invalidateProject);
- connect(sessionManager, &SessionManager::projectRemoved,
+ connect(sessionManager, &ProjectManager::projectRemoved,
this, &ProjectExplorerPlugin::fileListChanged);
- connect(sessionManager, &SessionManager::projectAdded,
+ connect(sessionManager, &ProjectManager::projectAdded,
dd, &ProjectExplorerPluginPrivate::projectAdded);
- connect(sessionManager, &SessionManager::projectRemoved,
+ connect(sessionManager, &ProjectManager::projectRemoved,
dd, &ProjectExplorerPluginPrivate::projectRemoved);
- connect(sessionManager, &SessionManager::projectDisplayNameChanged,
+ connect(sessionManager, &ProjectManager::projectDisplayNameChanged,
dd, &ProjectExplorerPluginPrivate::projectDisplayNameChanged);
- connect(sessionManager, &SessionManager::dependencyChanged,
+ connect(sessionManager, &ProjectManager::dependencyChanged,
dd, &ProjectExplorerPluginPrivate::updateActions);
- connect(sessionManager, &SessionManager::sessionLoaded,
+ connect(SessionManager::instance(), &SessionManager::sessionLoaded,
dd, &ProjectExplorerPluginPrivate::updateActions);
- connect(sessionManager, &SessionManager::sessionLoaded,
+ connect(SessionManager::instance(), &SessionManager::sessionLoaded,
dd, &ProjectExplorerPluginPrivate::updateWelcomePage);
- connect(sessionManager, &SessionManager::sessionLoaded,
+ connect(SessionManager::instance(), &SessionManager::sessionLoaded,
dd, &ProjectExplorerPluginPrivate::loadSesssionTasks);
-
- connect(sessionManager, &SessionManager::projectAdded, dd, [](ProjectExplorer::Project *project) {
- dd->m_allProjectDirectoriesFilter.addDirectory(project->projectDirectory());
- });
- connect(sessionManager,
- &SessionManager::projectRemoved,
- dd,
- [](ProjectExplorer::Project *project) {
- dd->m_allProjectDirectoriesFilter.removeDirectory(project->projectDirectory());
- });
+ connect(SessionManager::instance(), &SessionManager::sessionCreated,
+ dd, &ProjectExplorerPluginPrivate::updateWelcomePage);
+ connect(SessionManager::instance(), &SessionManager::sessionRenamed,
+ dd, &ProjectExplorerPluginPrivate::updateWelcomePage);
+ connect(SessionManager::instance(), &SessionManager::sessionRemoved,
+ dd, &ProjectExplorerPluginPrivate::updateWelcomePage);
ProjectTree *tree = &dd->m_projectTree;
connect(tree, &ProjectTree::currentProjectChanged, dd, [] {
@@ -903,7 +869,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
ICore::addPreCloseListener([]() -> bool { return coreAboutToClose(); });
- connect(SessionManager::instance(), &SessionManager::projectRemoved,
+ connect(ProjectManager::instance(), &ProjectManager::projectRemoved,
&dd->m_outputPane, &AppOutputPane::projectRemoved);
// ProjectPanelFactories
@@ -1182,23 +1148,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(mfile->menu(), &QMenu::aboutToShow,
dd, &ProjectExplorerPluginPrivate::updateRecentProjectMenu);
- // session menu
- ActionContainer *msession = ActionManager::createMenu(Constants::M_SESSION);
- msession->menu()->setTitle(Tr::tr("S&essions"));
- msession->setOnAllDisabledBehavior(ActionContainer::Show);
- mfile->addMenu(msession, Core::Constants::G_FILE_OPEN);
- dd->m_sessionMenu = msession->menu();
- connect(mfile->menu(), &QMenu::aboutToShow,
- dd, &ProjectExplorerPluginPrivate::updateSessionMenu);
-
- // session manager action
- dd->m_sessionManagerAction = new QAction(Tr::tr("&Manage..."), this);
- dd->m_sessionMenu->addAction(dd->m_sessionManagerAction);
- dd->m_sessionMenu->addSeparator();
- cmd = ActionManager::registerAction(dd->m_sessionManagerAction,
- "ProjectExplorer.ManageSessions");
- cmd->setDefaultKeySequence(QKeySequence());
-
// unload action
dd->m_unloadAction = new ParameterAction(Tr::tr("Close Project"), Tr::tr("Close Pro&ject \"%1\""),
ParameterAction::AlwaysEnabled, this);
@@ -1345,7 +1294,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// without a project loaded.
connect(generatorContainer->menu(), &QMenu::aboutToShow, [menu = generatorContainer->menu()] {
menu->clear();
- if (Project * const project = SessionManager::startupProject()) {
+ if (Project * const project = ProjectManager::startupProject()) {
for (const auto &generator : project->allGenerators()) {
menu->addAction(generator.second, [project, id = generator.first] {
project->runGenerator(id);
@@ -1620,7 +1569,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
Command * const expandCmd = ActionManager::registerAction(
dd->m_projectTreeExpandAllAction, Constants::PROJECTTREE_EXPAND_ALL,
projectTreeContext);
- for (Core::ActionContainer * const ac : {mfileContextMenu, msubProjectContextMenu,
+ for (ActionContainer * const ac : {mfileContextMenu, msubProjectContextMenu,
mfolderContextMenu, mprojectContextMenu, msessionContextMenu}) {
ac->addSeparator(treeGroup);
ac->addAction(expandNodeCmd, treeGroup);
@@ -1657,12 +1606,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(ICore::instance(), &ICore::saveSettingsRequested,
dd, &ProjectExplorerPluginPrivate::savePersistentSettings);
- connect(EditorManager::instance(), &EditorManager::autoSaved, this, [] {
- if (!dd->m_shuttingDown && !SessionManager::loadingSession())
- SessionManager::save();
- });
connect(qApp, &QApplication::applicationStateChanged, this, [](Qt::ApplicationState state) {
- if (!dd->m_shuttingDown && state == Qt::ApplicationActive)
+ if (!PluginManager::isShuttingDown() && state == Qt::ApplicationActive)
dd->updateWelcomePage();
});
@@ -1697,10 +1642,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
.toBool();
dd->m_projectExplorerSettings.useJom
= s->value(Constants::USE_JOM_SETTINGS_KEY, defaultSettings.useJom).toBool();
- dd->m_projectExplorerSettings.autorestoreLastSession
- = s->value(Constants::AUTO_RESTORE_SESSION_SETTINGS_KEY,
- defaultSettings.autorestoreLastSession)
- .toBool();
dd->m_projectExplorerSettings.addLibraryPathsToRunEnv
= s->value(Constants::ADD_LIBRARY_PATHS_TO_RUN_ENV_SETTINGS_KEY,
defaultSettings.addLibraryPathsToRunEnv)
@@ -1723,7 +1664,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
if (tmp < 0 || tmp > int(StopBeforeBuild::SameApp))
tmp = int(defaultSettings.stopBeforeBuild);
dd->m_projectExplorerSettings.stopBeforeBuild = StopBeforeBuild(tmp);
- dd->m_projectExplorerSettings.terminalMode = static_cast<ProjectExplorer::TerminalMode>(
+ dd->m_projectExplorerSettings.terminalMode = static_cast<TerminalMode>(
s->value(Constants::TERMINAL_MODE_SETTINGS_KEY, int(defaultSettings.terminalMode)).toInt());
dd->m_projectExplorerSettings.closeSourceFilesWithProject
= s->value(Constants::CLOSE_FILES_WITH_PROJECT_SETTINGS_KEY,
@@ -1757,27 +1698,25 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(buildManager, &BuildManager::buildQueueFinished,
dd, &ProjectExplorerPluginPrivate::buildQueueFinished, Qt::QueuedConnection);
- connect(dd->m_sessionManagerAction, &QAction::triggered,
- dd, &ProjectExplorerPluginPrivate::showSessionManager);
connect(dd->m_newAction, &QAction::triggered,
dd, &ProjectExplorerPlugin::openNewProjectDialog);
connect(dd->m_loadAction, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::loadAction);
connect(dd->m_buildProjectOnlyAction, &QAction::triggered, dd, [] {
- BuildManager::buildProjectWithoutDependencies(SessionManager::startupProject());
+ BuildManager::buildProjectWithoutDependencies(ProjectManager::startupProject());
});
connect(dd->m_buildAction, &QAction::triggered, dd, [] {
- BuildManager::buildProjectWithDependencies(SessionManager::startupProject());
+ BuildManager::buildProjectWithDependencies(ProjectManager::startupProject());
});
connect(dd->m_buildProjectForAllConfigsAction, &QAction::triggered, dd, [] {
- BuildManager::buildProjectWithDependencies(SessionManager::startupProject(),
+ BuildManager::buildProjectWithDependencies(ProjectManager::startupProject(),
ConfigSelection::All);
});
connect(dd->m_buildActionContextMenu, &QAction::triggered, dd, [] {
BuildManager::buildProjectWithoutDependencies(ProjectTree::currentProject());
});
connect(dd->m_buildForRunConfigAction, &QAction::triggered, dd, [] {
- const Project * const project = SessionManager::startupProject();
+ const Project * const project = ProjectManager::startupProject();
QTC_ASSERT(project, return);
const Target * const target = project->activeTarget();
QTC_ASSERT(target, return);
@@ -1792,20 +1731,20 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
BuildManager::buildProjectWithDependencies(ProjectTree::currentProject());
});
connect(dd->m_buildSessionAction, &QAction::triggered, dd, [] {
- BuildManager::buildProjects(SessionManager::projectOrder(), ConfigSelection::Active);
+ BuildManager::buildProjects(ProjectManager::projectOrder(), ConfigSelection::Active);
});
connect(dd->m_buildSessionForAllConfigsAction, &QAction::triggered, dd, [] {
- BuildManager::buildProjects(SessionManager::projectOrder(), ConfigSelection::All);
+ BuildManager::buildProjects(ProjectManager::projectOrder(), ConfigSelection::All);
});
connect(dd->m_rebuildProjectOnlyAction, &QAction::triggered, dd, [] {
- BuildManager::rebuildProjectWithoutDependencies(SessionManager::startupProject());
+ BuildManager::rebuildProjectWithoutDependencies(ProjectManager::startupProject());
});
connect(dd->m_rebuildAction, &QAction::triggered, dd, [] {
- BuildManager::rebuildProjectWithDependencies(SessionManager::startupProject(),
+ BuildManager::rebuildProjectWithDependencies(ProjectManager::startupProject(),
ConfigSelection::Active);
});
connect(dd->m_rebuildProjectForAllConfigsAction, &QAction::triggered, dd, [] {
- BuildManager::rebuildProjectWithDependencies(SessionManager::startupProject(),
+ BuildManager::rebuildProjectWithDependencies(ProjectManager::startupProject(),
ConfigSelection::All);
});
connect(dd->m_rebuildActionContextMenu, &QAction::triggered, dd, [] {
@@ -1816,32 +1755,32 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
ConfigSelection::Active);
});
connect(dd->m_rebuildSessionAction, &QAction::triggered, dd, [] {
- BuildManager::rebuildProjects(SessionManager::projectOrder(), ConfigSelection::Active);
+ BuildManager::rebuildProjects(ProjectManager::projectOrder(), ConfigSelection::Active);
});
connect(dd->m_rebuildSessionForAllConfigsAction, &QAction::triggered, dd, [] {
- BuildManager::rebuildProjects(SessionManager::projectOrder(), ConfigSelection::All);
+ BuildManager::rebuildProjects(ProjectManager::projectOrder(), ConfigSelection::All);
});
connect(dd->m_deployProjectOnlyAction, &QAction::triggered, dd, [] {
- BuildManager::deployProjects({SessionManager::startupProject()});
+ BuildManager::deployProjects({ProjectManager::startupProject()});
});
connect(dd->m_deployAction, &QAction::triggered, dd, [] {
- BuildManager::deployProjects(SessionManager::projectOrder(SessionManager::startupProject()));
+ BuildManager::deployProjects(ProjectManager::projectOrder(ProjectManager::startupProject()));
});
connect(dd->m_deployActionContextMenu, &QAction::triggered, dd, [] {
BuildManager::deployProjects({ProjectTree::currentProject()});
});
connect(dd->m_deploySessionAction, &QAction::triggered, dd, [] {
- BuildManager::deployProjects(SessionManager::projectOrder());
+ BuildManager::deployProjects(ProjectManager::projectOrder());
});
connect(dd->m_cleanProjectOnlyAction, &QAction::triggered, dd, [] {
- BuildManager::cleanProjectWithoutDependencies(SessionManager::startupProject());
+ BuildManager::cleanProjectWithoutDependencies(ProjectManager::startupProject());
});
connect(dd->m_cleanAction, &QAction::triggered, dd, [] {
- BuildManager::cleanProjectWithDependencies(SessionManager::startupProject(),
+ BuildManager::cleanProjectWithDependencies(ProjectManager::startupProject(),
ConfigSelection::Active);
});
connect(dd->m_cleanProjectForAllConfigsAction, &QAction::triggered, dd, [] {
- BuildManager::cleanProjectWithDependencies(SessionManager::startupProject(),
+ BuildManager::cleanProjectWithDependencies(ProjectManager::startupProject(),
ConfigSelection::All);
});
connect(dd->m_cleanActionContextMenu, &QAction::triggered, dd, [] {
@@ -1852,10 +1791,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
ConfigSelection::Active);
});
connect(dd->m_cleanSessionAction, &QAction::triggered, dd, [] {
- BuildManager::cleanProjects(SessionManager::projectOrder(), ConfigSelection::Active);
+ BuildManager::cleanProjects(ProjectManager::projectOrder(), ConfigSelection::Active);
});
connect(dd->m_cleanSessionForAllConfigsAction, &QAction::triggered, dd, [] {
- BuildManager::cleanProjects(SessionManager::projectOrder(), ConfigSelection::All);
+ BuildManager::cleanProjects(ProjectManager::projectOrder(), ConfigSelection::All);
});
connect(dd->m_runAction, &QAction::triggered,
dd, [] { runStartupProject(Constants::NORMAL_RUN_MODE); });
@@ -1920,7 +1859,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(dd->m_setStartupProjectAction, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::handleSetStartupProject);
connect(dd->m_closeProjectFilesActionFileMenu, &QAction::triggered,
- dd, [] { dd->closeAllFilesInProject(SessionManager::projects().first()); });
+ dd, [] { dd->closeAllFilesInProject(ProjectManager::projects().first()); });
connect(dd->m_closeProjectFilesActionContextMenu, &QAction::triggered,
dd, [] { dd->closeAllFilesInProject(ProjectTree::currentProject()); });
connect(dd->m_projectTreeCollapseAllAction, &QAction::triggered,
@@ -1935,6 +1874,18 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd->updateContextMenuActions(ProjectTree::currentNode());
});
+ connect(ModeManager::instance(),
+ &ModeManager::currentModeChanged,
+ dd,
+ &ProjectExplorerPluginPrivate::currentModeChanged);
+ connect(&dd->m_welcomePage,
+ &ProjectWelcomePage::requestProject,
+ m_instance,
+ &ProjectExplorerPlugin::openProjectWelcomePage);
+ connect(SessionManager::instance(),
+ &SessionManager::startupSessionRestored,
+ m_instance,
+ &ProjectExplorerPlugin::finishedInitialization);
dd->updateWelcomePage();
MacroExpander *expander = Utils::globalMacroExpander();
@@ -1965,7 +1916,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
Project::addVariablesToMacroExpander("ActiveProject:",
"Active project",
expander,
- &SessionManager::startupProject);
+ &ProjectManager::startupProject);
EnvironmentProvider::addProvider(
{"ActiveProject:BuildConfig:Env", Tr::tr("Active build environment of the active project."), [] {
if (const BuildConfiguration * const bc = activeBuildConfiguration())
@@ -1981,15 +1932,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
return Environment::systemEnvironment();
}});
- const auto fileHandler = [] {
- return SessionManager::sessionNameToFileName(SessionManager::activeSession());
- };
- expander->registerFileVariables("Session", Tr::tr("File where current session is saved."),
- fileHandler);
- expander->registerVariable("Session:Name", Tr::tr("Name of current session."), [] {
- return SessionManager::activeSession();
- });
-
DeviceManager::instance()->addDevice(IDevice::Ptr(new DesktopDevice));
if (auto sanitizerTester = SanitizerParser::testCreator())
@@ -2032,7 +1974,7 @@ void ProjectExplorerPluginPrivate::unloadProjectContextMenu()
void ProjectExplorerPluginPrivate::unloadOtherProjectsContextMenu()
{
if (Project *currentProject = ProjectTree::currentProject()) {
- const QList<Project *> projects = SessionManager::projects();
+ const QList<Project *> projects = ProjectManager::projects();
QTC_ASSERT(!projects.isEmpty(), return);
for (Project *p : projects) {
@@ -2045,7 +1987,7 @@ void ProjectExplorerPluginPrivate::unloadOtherProjectsContextMenu()
void ProjectExplorerPluginPrivate::handleUnloadProject()
{
- QList<Project *> projects = SessionManager::projects();
+ QList<Project *> projects = ProjectManager::projects();
QTC_ASSERT(!projects.isEmpty(), return);
ProjectExplorerPlugin::unloadProject(projects.first());
@@ -2072,7 +2014,7 @@ void ProjectExplorerPlugin::unloadProject(Project *project)
dd->addToRecentProjects(project->projectFilePath(), project->displayName());
- SessionManager::removeProject(project);
+ ProjectManager::removeProject(project);
dd->updateActions();
}
@@ -2081,7 +2023,7 @@ void ProjectExplorerPluginPrivate::closeAllProjects()
if (!EditorManager::closeAllDocuments())
return; // Action has been cancelled
- SessionManager::closeAllProjects();
+ ProjectManager::closeAllProjects();
updateActions();
ModeManager::activateMode(Core::Constants::MODE_WELCOME);
@@ -2137,13 +2079,13 @@ void ProjectExplorerPlugin::extensionsInitialized()
Tr::tr("Sanitizer", "Category for sanitizer issues listed under 'Issues'"));
TaskHub::addCategory(Constants::TASK_CATEGORY_TASKLIST_ID, Tr::tr("My Tasks"));
- SshSettings::loadSettings(Core::ICore::settings());
+ SshSettings::loadSettings(ICore::settings());
const auto searchPathRetriever = [] {
- FilePaths searchPaths = {Core::ICore::libexecPath()};
+ FilePaths searchPaths = {ICore::libexecPath()};
if (HostOsInfo::isWindowsHost()) {
- const QString gitBinary = Core::ICore::settings()->value("Git/BinaryPath", "git")
+ const QString gitBinary = ICore::settings()->value("Git/BinaryPath", "git")
.toString();
- const QStringList rawGitSearchPaths = Core::ICore::settings()->value("Git/Path")
+ const QStringList rawGitSearchPaths = ICore::settings()->value("Git/Path")
.toString().split(':', Qt::SkipEmptyParts);
const FilePaths gitSearchPaths = Utils::transform(rawGitSearchPaths,
[](const QString &rawPath) { return FilePath::fromString(rawPath); });
@@ -2177,11 +2119,12 @@ void ProjectExplorerPlugin::extensionsInitialized()
void ProjectExplorerPlugin::restoreKits()
{
- dd->determineSessionToRestoreAtStartup();
ExtraAbi::load(); // Load this before Toolchains!
ToolChainManager::restoreToolChains();
KitManager::restoreKits();
- QTimer::singleShot(0, dd, &ProjectExplorerPluginPrivate::restoreSession); // delay a bit...
+ // restoring startup session is supposed to be done as a result of ICore::coreOpened,
+ // and that is supposed to happen after restoring kits:
+ QTC_CHECK(!SessionManager::isStartupSessionRestored());
}
void ProjectExplorerPluginPrivate::updateRunWithoutDeployMenu()
@@ -2189,15 +2132,13 @@ void ProjectExplorerPluginPrivate::updateRunWithoutDeployMenu()
m_runWithoutDeployAction->setVisible(m_projectExplorerSettings.deployBeforeRun);
}
-ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown()
+IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown()
{
disconnect(ModeManager::instance(), &ModeManager::currentModeChanged,
dd, &ProjectExplorerPluginPrivate::currentModeChanged);
ProjectTree::aboutToShutDown();
ToolChainManager::aboutToShutdown();
- SessionManager::closeAllProjects();
-
- dd->m_shuttingDown = true;
+ ProjectManager::closeAllProjects();
// Attempt to synchronously shutdown all run controls.
// If that fails, fall back to asynchronous shutdown (Debugger run controls
@@ -2210,11 +2151,6 @@ ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown()
return AsynchronousShutdown;
}
-void ProjectExplorerPlugin::showSessionManager()
-{
- dd->showSessionManager();
-}
-
void ProjectExplorerPlugin::openNewProjectDialog()
{
if (!ICore::isNewItemDialogRunning()) {
@@ -2226,25 +2162,11 @@ void ProjectExplorerPlugin::openNewProjectDialog()
}
}
-void ProjectExplorerPluginPrivate::showSessionManager()
-{
- SessionManager::save();
- SessionDialog sessionDialog(ICore::dialogParent());
- sessionDialog.setAutoLoadSession(dd->m_projectExplorerSettings.autorestoreLastSession);
- sessionDialog.exec();
- dd->m_projectExplorerSettings.autorestoreLastSession = sessionDialog.autoLoadSession();
-
- updateActions();
-
- if (ModeManager::currentModeId() == Core::Constants::MODE_WELCOME)
- updateWelcomePage();
-}
-
void ProjectExplorerPluginPrivate::setStartupProject(Project *project)
{
if (!project)
return;
- SessionManager::setStartupProject(project);
+ ProjectManager::setStartupProject(project);
updateActions();
}
@@ -2255,7 +2177,7 @@ bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project
Utils::erase(openFiles, [project](const DocumentModel::Entry *entry) {
return entry->pinned || !project->isKnownFile(entry->filePath());
});
- for (const Project * const otherProject : SessionManager::projects()) {
+ for (const Project * const otherProject : ProjectManager::projects()) {
if (otherProject == project)
continue;
Utils::erase(openFiles, [otherProject](const DocumentModel::Entry *entry) {
@@ -2267,23 +2189,15 @@ bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project
void ProjectExplorerPluginPrivate::savePersistentSettings()
{
- if (dd->m_shuttingDown)
+ if (PluginManager::isShuttingDown())
return;
- if (!SessionManager::loadingSession()) {
- for (Project *pro : SessionManager::projects())
+ if (!SessionManager::isLoadingSession()) {
+ for (Project *pro : ProjectManager::projects())
pro->saveSettings();
-
- SessionManager::save();
}
QtcSettings *s = ICore::settings();
- if (SessionManager::isDefaultVirgin()) {
- s->remove(Constants::STARTUPSESSION_KEY);
- } else {
- s->setValue(Constants::STARTUPSESSION_KEY, SessionManager::activeSession());
- s->setValue(Constants::LASTSESSION_KEY, SessionManager::activeSession());
- }
s->remove(QLatin1String("ProjectExplorer/RecentProjects/Files"));
QStringList fileNames;
@@ -2312,9 +2226,6 @@ void ProjectExplorerPluginPrivate::savePersistentSettings()
s->setValueWithDefault(Constants::USE_JOM_SETTINGS_KEY,
dd->m_projectExplorerSettings.useJom,
defaultSettings.useJom);
- s->setValueWithDefault(Constants::AUTO_RESTORE_SESSION_SETTINGS_KEY,
- dd->m_projectExplorerSettings.autorestoreLastSession,
- defaultSettings.autorestoreLastSession);
s->setValueWithDefault(Constants::ADD_LIBRARY_PATHS_TO_RUN_ENV_SETTINGS_KEY,
dd->m_projectExplorerSettings.addLibraryPathsToRunEnv,
defaultSettings.addLibraryPathsToRunEnv);
@@ -2368,7 +2279,7 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProject(cons
if (!project)
return result;
dd->addToRecentProjects(filePath, project->displayName());
- SessionManager::setStartupProject(project);
+ ProjectManager::setStartupProject(project);
return result;
}
@@ -2420,11 +2331,11 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
QTC_ASSERT(!fileName.isEmpty(), continue);
const FilePath filePath = fileName.absoluteFilePath();
- Project *found = Utils::findOrDefault(SessionManager::projects(),
+ Project *found = Utils::findOrDefault(ProjectManager::projects(),
Utils::equal(&Project::projectFilePath, filePath));
if (found) {
alreadyOpen.append(found);
- SessionManager::reportProjectLoadingProgress();
+ SessionManager::sessionLoadingProgress();
continue;
}
@@ -2439,7 +2350,7 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
if (restoreResult == Project::RestoreResult::Ok) {
connect(pro, &Project::fileListChanged,
m_instance, &ProjectExplorerPlugin::fileListChanged);
- SessionManager::addProject(pro);
+ ProjectManager::addProject(pro);
openedPro += pro;
} else {
if (restoreResult == Project::RestoreResult::Error)
@@ -2453,7 +2364,7 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
.arg(mt.name()));
}
if (filePaths.size() > 1)
- SessionManager::reportProjectLoadingProgress();
+ SessionManager::sessionLoadingProgress();
}
dd->updateActions();
@@ -2496,33 +2407,6 @@ void ProjectExplorerPluginPrivate::currentModeChanged(Id mode, Id oldMode)
updateWelcomePage();
}
-void ProjectExplorerPluginPrivate::determineSessionToRestoreAtStartup()
-{
- // Process command line arguments first:
- const bool lastSessionArg =
- ExtensionSystem::PluginManager::specForPlugin(m_instance)->arguments().contains("-lastsession");
- m_sessionToRestoreAtStartup = lastSessionArg ? SessionManager::startupSession() : QString();
- const QStringList arguments = ExtensionSystem::PluginManager::arguments();
- if (!lastSessionArg) {
- QStringList sessions = SessionManager::sessions();
- // We have command line arguments, try to find a session in them
- // Default to no session loading
- for (const QString &arg : arguments) {
- if (sessions.contains(arg)) {
- // Session argument
- m_sessionToRestoreAtStartup = arg;
- break;
- }
- }
- }
- // Handle settings only after command line arguments:
- if (m_sessionToRestoreAtStartup.isEmpty() && m_projectExplorerSettings.autorestoreLastSession)
- m_sessionToRestoreAtStartup = SessionManager::startupSession();
-
- if (!m_sessionToRestoreAtStartup.isEmpty())
- ModeManager::activateMode(Core::Constants::MODE_EDIT);
-}
-
// Return a list of glob patterns for project files ("*.pro", etc), use first, main pattern only.
QStringList ProjectExplorerPlugin::projectFileGlobs()
{
@@ -2548,70 +2432,6 @@ MiniProjectTargetSelector *ProjectExplorerPlugin::targetSelector()
return dd->m_targetSelector;
}
-/*!
- This function is connected to the ICore::coreOpened signal. If
- there was no session explicitly loaded, it creates an empty new
- default session and puts the list of recent projects and sessions
- onto the welcome page.
-*/
-void ProjectExplorerPluginPrivate::restoreSession()
-{
- // We have command line arguments, try to find a session in them
- QStringList arguments = ExtensionSystem::PluginManager::arguments();
- if (!dd->m_sessionToRestoreAtStartup.isEmpty() && !arguments.isEmpty())
- arguments.removeOne(dd->m_sessionToRestoreAtStartup);
-
- // Massage the argument list.
- // Be smart about directories: If there is a session of that name, load it.
- // Other than that, look for project files in it. The idea is to achieve
- // 'Do what I mean' functionality when starting Creator in a directory with
- // the single command line argument '.' and avoid editor warnings about not
- // being able to open directories.
- // In addition, convert "filename" "+45" or "filename" ":23" into
- // "filename+45" and "filename:23".
- if (!arguments.isEmpty()) {
- const QStringList sessions = SessionManager::sessions();
- for (int a = 0; a < arguments.size(); ) {
- const QString &arg = arguments.at(a);
- const QFileInfo fi(arg);
- if (fi.isDir()) {
- const QDir dir(fi.absoluteFilePath());
- // Does the directory name match a session?
- if (dd->m_sessionToRestoreAtStartup.isEmpty()
- && sessions.contains(dir.dirName())) {
- dd->m_sessionToRestoreAtStartup = dir.dirName();
- arguments.removeAt(a);
- continue;
- }
- } // Done directories.
- // Converts "filename" "+45" or "filename" ":23" into "filename+45" and "filename:23"
- if (a && (arg.startsWith(QLatin1Char('+')) || arg.startsWith(QLatin1Char(':')))) {
- arguments[a - 1].append(arguments.takeAt(a));
- continue;
- }
- ++a;
- } // for arguments
- } // !arguments.isEmpty()
- // Restore latest session or what was passed on the command line
-
- SessionManager::loadSession(!dd->m_sessionToRestoreAtStartup.isEmpty()
- ? dd->m_sessionToRestoreAtStartup : QString(), true);
-
- // update welcome page
- connect(ModeManager::instance(), &ModeManager::currentModeChanged,
- dd, &ProjectExplorerPluginPrivate::currentModeChanged);
- connect(&dd->m_welcomePage, &ProjectWelcomePage::requestProject,
- m_instance, &ProjectExplorerPlugin::openProjectWelcomePage);
- dd->m_arguments = arguments;
- // delay opening projects from the command line even more
- QTimer::singleShot(0, m_instance, [] {
- ICore::openFiles(Utils::transform(dd->m_arguments, &FilePath::fromUserInput),
- ICore::OpenFilesFlags(ICore::CanContainLineAndColumnNumbers | ICore::SwitchMode));
- emit m_instance->finishedInitialization();
- });
- updateActions();
-}
-
void ProjectExplorerPluginPrivate::executeRunConfiguration(RunConfiguration *runConfiguration, Id runMode)
{
const Tasks runConfigIssues = runConfiguration->checkForIssues();
@@ -2675,7 +2495,7 @@ void ProjectExplorerPluginPrivate::checkForShutdown()
{
--m_activeRunControlCount;
QTC_ASSERT(m_activeRunControlCount >= 0, m_activeRunControlCount = 0);
- if (m_shuttingDown && m_activeRunControlCount == 0)
+ if (PluginManager::isShuttingDown() && m_activeRunControlCount == 0)
emit m_instance->asynchronousShutdownFinished();
}
@@ -2732,7 +2552,7 @@ RecentProjectsEntries ProjectExplorerPluginPrivate::recentProjects() const
void ProjectExplorerPluginPrivate::updateActions()
{
- const Project *const project = SessionManager::startupProject();
+ const Project *const project = ProjectManager::startupProject();
const Project *const currentProject = ProjectTree::currentProject(); // for context menu actions
const QPair<bool, QString> buildActionState = buildSettingsEnabled(project);
@@ -2743,10 +2563,10 @@ void ProjectExplorerPluginPrivate::updateActions()
const QString projectName = project ? project->displayName() : QString();
const QString projectNameContextMenu = currentProject ? currentProject->displayName() : QString();
- m_unloadAction->setParameter(SessionManager::projects().size() == 1 ? projectName : QString());
+ m_unloadAction->setParameter(ProjectManager::projects().size() == 1 ? projectName : QString());
m_unloadActionContextMenu->setParameter(projectNameContextMenu);
m_unloadOthersActionContextMenu->setParameter(projectNameContextMenu);
- m_closeProjectFilesActionFileMenu->setParameter(SessionManager::projects().size() == 1
+ m_closeProjectFilesActionFileMenu->setParameter(ProjectManager::projects().size() == 1
? projectName : QString());
m_closeProjectFilesActionContextMenu->setParameter(projectNameContextMenu);
@@ -2791,7 +2611,7 @@ void ProjectExplorerPluginPrivate::updateActions()
m_setStartupProjectAction->setParameter(projectNameContextMenu);
m_setStartupProjectAction->setVisible(currentProject != project);
- const bool hasDependencies = SessionManager::projectOrder(currentProject).size() > 1;
+ const bool hasDependencies = ProjectManager::projectOrder(currentProject).size() > 1;
m_buildActionContextMenu->setVisible(hasDependencies);
m_rebuildActionContextMenu->setVisible(hasDependencies);
m_cleanActionContextMenu->setVisible(hasDependencies);
@@ -2818,17 +2638,17 @@ void ProjectExplorerPluginPrivate::updateActions()
m_cleanProjectOnlyAction->setToolTip(buildActionState.second);
// Session actions
- m_closeAllProjects->setEnabled(SessionManager::hasProjects());
- m_unloadAction->setEnabled(SessionManager::projects().size() <= 1);
- m_unloadAction->setEnabled(SessionManager::projects().size() == 1);
- m_unloadActionContextMenu->setEnabled(SessionManager::hasProjects());
- m_unloadOthersActionContextMenu->setEnabled(SessionManager::projects().size() >= 2);
- m_closeProjectFilesActionFileMenu->setEnabled(SessionManager::projects().size() == 1);
- m_closeProjectFilesActionContextMenu->setEnabled(SessionManager::hasProjects());
+ m_closeAllProjects->setEnabled(ProjectManager::hasProjects());
+ m_unloadAction->setEnabled(ProjectManager::projects().size() <= 1);
+ m_unloadAction->setEnabled(ProjectManager::projects().size() == 1);
+ m_unloadActionContextMenu->setEnabled(ProjectManager::hasProjects());
+ m_unloadOthersActionContextMenu->setEnabled(ProjectManager::projects().size() >= 2);
+ m_closeProjectFilesActionFileMenu->setEnabled(ProjectManager::projects().size() == 1);
+ m_closeProjectFilesActionContextMenu->setEnabled(ProjectManager::hasProjects());
ActionContainer *aci =
ActionManager::actionContainer(Constants::M_UNLOADPROJECTS);
- aci->menu()->menuAction()->setEnabled(SessionManager::hasProjects());
+ aci->menu()->menuAction()->setEnabled(ProjectManager::hasProjects());
m_buildSessionAction->setEnabled(buildSessionState.first);
m_buildSessionForAllConfigsAction->setEnabled(buildSessionState.first);
@@ -2846,7 +2666,7 @@ void ProjectExplorerPluginPrivate::updateActions()
m_cancelBuildAction->setEnabled(BuildManager::isBuilding());
- const bool hasProjects = SessionManager::hasProjects();
+ const bool hasProjects = ProjectManager::hasProjects();
m_projectSelectorAction->setEnabled(hasProjects);
m_projectSelectorActionMenu->setEnabled(hasProjects);
m_projectSelectorActionQuick->setEnabled(hasProjects);
@@ -2923,10 +2743,9 @@ void ProjectExplorerPluginPrivate::extendFolderNavigationWidgetFactory()
"The file \"%1\" was renamed to \"%2\", "
"but the following projects could not be automatically changed: %3")
.arg(before.toUserOutput(), after.toUserOutput(), projects);
- QTimer::singleShot(0, Core::ICore::instance(), [errorMessage] {
- QMessageBox::warning(Core::ICore::dialogParent(),
- Tr::tr("Project Editing Failed"),
- errorMessage);
+ QTimer::singleShot(0, ICore::instance(), [errorMessage] {
+ QMessageBox::warning(ICore::dialogParent(),
+ Tr::tr("Project Editing Failed"), errorMessage);
});
}
});
@@ -2944,8 +2763,8 @@ void ProjectExplorerPluginPrivate::extendFolderNavigationWidgetFactory()
const QString errorMessage
= Tr::tr("The following projects failed to automatically remove the file: %1")
.arg(projects);
- QTimer::singleShot(0, Core::ICore::instance(), [errorMessage] {
- QMessageBox::warning(Core::ICore::dialogParent(),
+ QTimer::singleShot(0, ICore::instance(), [errorMessage] {
+ QMessageBox::warning(ICore::dialogParent(),
Tr::tr("Project Editing Failed"),
errorMessage);
});
@@ -2967,7 +2786,7 @@ void ProjectExplorerPluginPrivate::runProjectContextMenu(RunConfiguration *rc)
static bool hasBuildSettings(const Project *pro)
{
- return Utils::anyOf(SessionManager::projectOrder(pro), [](const Project *project) {
+ return Utils::anyOf(ProjectManager::projectOrder(pro), [](const Project *project) {
return project
&& project->activeTarget()
&& project->activeTarget()->activeBuildConfiguration();
@@ -2979,7 +2798,7 @@ static QPair<bool, QString> subprojectEnabledState(const Project *pro)
QPair<bool, QString> result;
result.first = true;
- const QList<Project *> &projects = SessionManager::projectOrder(pro);
+ const QList<Project *> &projects = ProjectManager::projectOrder(pro);
for (const Project *project : projects) {
if (project && project->activeTarget()
&& project->activeTarget()->activeBuildConfiguration()
@@ -3021,7 +2840,7 @@ QPair<bool, QString> ProjectExplorerPluginPrivate::buildSettingsEnabledForSessio
{
QPair<bool, QString> result;
result.first = true;
- if (!SessionManager::hasProjects()) {
+ if (!ProjectManager::hasProjects()) {
result.first = false;
result.second = Tr::tr("No project loaded.");
} else if (BuildManager::isBuilding()) {
@@ -3078,7 +2897,7 @@ void ProjectExplorerPlugin::handleCommandLineArguments(const QStringList &argume
static bool hasDeploySettings(Project *pro)
{
- return Utils::anyOf(SessionManager::projectOrder(pro), [](Project *project) {
+ return Utils::anyOf(ProjectManager::projectOrder(pro), [](Project *project) {
return project->activeTarget()
&& project->activeTarget()->activeDeployConfiguration();
});
@@ -3096,7 +2915,7 @@ void ProjectExplorerPlugin::runProject(Project *pro, Id mode, const bool forceSk
void ProjectExplorerPlugin::runStartupProject(Id runMode, bool forceSkipDeploy)
{
- runProject(SessionManager::startupProject(), runMode, forceSkipDeploy);
+ runProject(ProjectManager::startupProject(), runMode, forceSkipDeploy);
}
void ProjectExplorerPlugin::runRunConfiguration(RunConfiguration *rc,
@@ -3157,7 +2976,7 @@ void ProjectExplorerPluginPrivate::projectAdded(Project *pro)
void ProjectExplorerPluginPrivate::projectRemoved(Project *pro)
{
Q_UNUSED(pro)
- m_projectsMode.setEnabled(SessionManager::hasProjects());
+ m_projectsMode.setEnabled(ProjectManager::hasProjects());
}
void ProjectExplorerPluginPrivate::projectDisplayNameChanged(Project *pro)
@@ -3168,7 +2987,7 @@ void ProjectExplorerPluginPrivate::projectDisplayNameChanged(Project *pro)
void ProjectExplorerPluginPrivate::updateDeployActions()
{
- Project *project = SessionManager::startupProject();
+ Project *project = ProjectManager::startupProject();
bool enableDeployActions = project
&& !BuildManager::isBuilding(project)
@@ -3187,7 +3006,7 @@ void ProjectExplorerPluginPrivate::updateDeployActions()
enableDeployActionsContextMenu = false;
}
- bool hasProjects = SessionManager::hasProjects();
+ bool hasProjects = ProjectManager::hasProjects();
m_deployAction->setEnabled(enableDeployActions);
@@ -3203,7 +3022,7 @@ void ProjectExplorerPluginPrivate::updateDeployActions()
&& !project->activeTarget()->activeBuildConfiguration()->isEnabled();
};
- if (Utils::anyOf(SessionManager::projectOrder(nullptr), hasDisabledBuildConfiguration))
+ if (Utils::anyOf(ProjectManager::projectOrder(nullptr), hasDisabledBuildConfiguration))
enableDeploySessionAction = false;
}
if (!hasProjects || !hasDeploySettings(nullptr) || BuildManager::isBuilding())
@@ -3215,7 +3034,7 @@ void ProjectExplorerPluginPrivate::updateDeployActions()
bool ProjectExplorerPlugin::canRunStartupProject(Id runMode, QString *whyNot)
{
- Project *project = SessionManager::startupProject();
+ Project *project = ProjectManager::startupProject();
if (!project) {
if (whyNot)
*whyNot = Tr::tr("No active project.");
@@ -3320,7 +3139,7 @@ void ProjectExplorerPluginPrivate::updateUnloadProjectMenu()
ActionContainer *aci = ActionManager::actionContainer(Constants::M_UNLOADPROJECTS);
QMenu *menu = aci->menu();
menu->clear();
- for (Project *project : SessionManager::projects()) {
+ for (Project *project : ProjectManager::projects()) {
QAction *action = menu->addAction(Tr::tr("Close Project \"%1\"").arg(project->displayName()));
connect(action, &QAction::triggered,
[project] { ProjectExplorerPlugin::unloadProject(project); } );
@@ -3419,7 +3238,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions(Node *currentNode)
m_removeFileAction->setVisible(true);
m_duplicateFileAction->setVisible(false);
m_deleteFileAction->setVisible(true);
- m_runActionContextMenu->setVisible(false);
+ m_runActionContextMenu->setEnabled(false);
m_defaultRunConfiguration.clear();
m_diffFileAction->setVisible(DiffService::instance());
@@ -3448,7 +3267,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions(Node *currentNode)
if (pn && project) {
if (pn == project->rootProjectNode()) {
- m_runActionContextMenu->setVisible(true);
+ m_runActionContextMenu->setEnabled(true);
} else {
QList<RunConfiguration *> runConfigs;
if (Target *t = project->activeTarget()) {
@@ -3459,7 +3278,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions(Node *currentNode)
}
}
if (runConfigs.count() == 1) {
- m_runActionContextMenu->setVisible(true);
+ m_runActionContextMenu->setEnabled(true);
m_defaultRunConfiguration = runConfigs.first();
} else if (runConfigs.count() > 1) {
runMenu->menu()->menuAction()->setVisible(true);
@@ -3592,9 +3411,7 @@ void ProjectExplorerPluginPrivate::updateLocationSubMenus()
: Tr::tr("%1 in %2").arg(li.displayName).arg(li.path.toUserOutput());
auto *action = new QAction(displayName, nullptr);
connect(action, &QAction::triggered, this, [line, path] {
- Core::EditorManager::openEditorAt(Link(path, line),
- {},
- Core::EditorManager::AllowExternalEditor);
+ EditorManager::openEditorAt(Link(path, line), {}, EditorManager::AllowExternalEditor);
});
projectMenu->addAction(action);
@@ -3795,6 +3612,13 @@ void ProjectExplorerPluginPrivate::showInFileSystemPane()
Core::FileUtils::showInFileSystemView(currentNode->filePath());
}
+static BuildConfiguration *activeBuildConfiguration(Project *project)
+{
+ if (!project || !project->activeTarget() || !project->activeTarget()->activeBuildConfiguration())
+ return {};
+ return project->activeTarget()->activeBuildConfiguration();
+}
+
void ProjectExplorerPluginPrivate::openTerminalHere(const EnvironmentGetter &env)
{
const Node *currentNode = ProjectTree::currentNode();
@@ -3804,7 +3628,29 @@ void ProjectExplorerPluginPrivate::openTerminalHere(const EnvironmentGetter &env
if (!environment)
return;
- Core::FileUtils::openTerminal(currentNode->directory(), environment.value());
+ BuildConfiguration *bc = activeBuildConfiguration(ProjectTree::projectForNode(currentNode));
+ if (!bc) {
+ Terminal::Hooks::instance().openTerminal({{}, currentNode->directory(), environment});
+ return;
+ }
+
+ IDeviceConstPtr buildDevice = BuildDeviceKitAspect::device(bc->target()->kit());
+
+ if (!buildDevice)
+ return;
+
+ FilePath workingDir = currentNode->directory();
+ if (!buildDevice->filePath(workingDir.path()).exists()
+ && !buildDevice->ensureReachable(workingDir))
+ workingDir.clear();
+
+ const FilePath shell = Terminal::defaultShellForDevice(buildDevice->rootPath());
+
+ if (!shell.isEmpty() && buildDevice->rootPath().needsDevice()) {
+ Terminal::Hooks::instance().openTerminal({CommandLine{shell, {}}, workingDir, environment});
+ } else {
+ Terminal::Hooks::instance().openTerminal({std::nullopt, workingDir, environment});
+ }
}
void ProjectExplorerPluginPrivate::openTerminalHereWithRunEnv()
@@ -3825,9 +3671,21 @@ void ProjectExplorerPluginPrivate::openTerminalHereWithRunEnv()
if (!device)
device = DeviceKitAspect::device(target->kit());
QTC_ASSERT(device && device->canOpenTerminal(), return);
- const FilePath workingDir = device->type() == Constants::DESKTOP_DEVICE_TYPE
- ? currentNode->directory() : runnable.workingDirectory;
- device->openTerminal(runnable.environment, workingDir);
+
+ FilePath workingDir = device->type() == Constants::DESKTOP_DEVICE_TYPE
+ ? currentNode->directory()
+ : runnable.workingDirectory;
+
+ if (!device->filePath(workingDir.path()).exists() && !device->ensureReachable(workingDir))
+ workingDir.clear();
+
+ const FilePath shell = Terminal::defaultShellForDevice(device->rootPath());
+ if (!shell.isEmpty() && device->rootPath().needsDevice()) {
+ Terminal::Hooks::instance().openTerminal(
+ {CommandLine{shell, {}}, workingDir, runnable.environment});
+ } else {
+ Terminal::Hooks::instance().openTerminal({std::nullopt, workingDir, runnable.environment});
+ }
}
void ProjectExplorerPluginPrivate::removeFile()
@@ -3852,7 +3710,7 @@ void ProjectExplorerPluginPrivate::removeFile()
if (!siblings.isEmpty()) {
const QMessageBox::StandardButton reply = QMessageBox::question(
- Core::ICore::dialogParent(), Tr::tr("Remove More Files?"),
+ ICore::dialogParent(), Tr::tr("Remove More Files?"),
Tr::tr("Remove these files as well?\n %1")
.arg(Utils::transform<QStringList>(siblings, [](const NodeAndPath &np) {
return np.second.fileName();
@@ -4058,41 +3916,6 @@ void ProjectExplorerPluginPrivate::handleSetStartupProject()
setStartupProject(ProjectTree::currentProject());
}
-void ProjectExplorerPluginPrivate::updateSessionMenu()
-{
- m_sessionMenu->clear();
- dd->m_sessionMenu->addAction(dd->m_sessionManagerAction);
- dd->m_sessionMenu->addSeparator();
- auto *ag = new QActionGroup(m_sessionMenu);
- connect(ag, &QActionGroup::triggered, this, &ProjectExplorerPluginPrivate::setSession);
- const QString activeSession = SessionManager::activeSession();
- const bool isDefaultVirgin = SessionManager::isDefaultVirgin();
-
- QStringList sessions = SessionManager::sessions();
- std::sort(std::next(sessions.begin()), sessions.end(), [](const QString &s1, const QString &s2) {
- return SessionManager::lastActiveTime(s1) > SessionManager::lastActiveTime(s2);
- });
- for (int i = 0; i < sessions.size(); ++i) {
- const QString &session = sessions[i];
-
- const QString actionText = ActionManager::withNumberAccelerator(Utils::quoteAmpersands(
- session),
- i + 1);
- QAction *act = ag->addAction(actionText);
- act->setData(session);
- act->setCheckable(true);
- if (session == activeSession && !isDefaultVirgin)
- act->setChecked(true);
- }
- m_sessionMenu->addActions(ag->actions());
- m_sessionMenu->setEnabled(true);
-}
-
-void ProjectExplorerPluginPrivate::setSession(QAction *action)
-{
- SessionManager::loadSession(action->data().toString());
-}
-
void ProjectExplorerPlugin::setProjectExplorerSettings(const ProjectExplorerSettings &pes)
{
QTC_ASSERT(dd->m_projectExplorerSettings.environmentId == pes.environmentId, return);
@@ -4213,7 +4036,7 @@ void ProjectExplorerPlugin::updateActions()
void ProjectExplorerPlugin::activateProjectPanel(Id panelId)
{
- Core::ModeManager::activateMode(Constants::MODE_SESSION);
+ ModeManager::activateMode(Constants::MODE_SESSION);
dd->m_proWindow->activateProjectPanel(panelId);
}
@@ -4242,9 +4065,8 @@ RecentProjectsEntries ProjectExplorerPlugin::recentProjects()
return dd->recentProjects();
}
-void ProjectExplorerPlugin::renameFilesForSymbol(
- const QString &oldSymbolName, const QString &newSymbolName, const Utils::FilePaths &files,
- bool preferLowerCaseFileNames)
+void ProjectExplorerPlugin::renameFilesForSymbol(const QString &oldSymbolName,
+ const QString &newSymbolName, const FilePaths &files, bool preferLowerCaseFileNames)
{
static const auto isAllLowerCase = [](const QString &text) { return text.toLower() == text; };
@@ -4319,10 +4141,18 @@ AllProjectFilesFilter::AllProjectFilesFilter()
setDefaultIncludedByDefault(false); // but not included in default
setFilters({});
setIsCustomFilter(false);
- setDescription(Tr::tr(
- "Matches all files from all project directories. Append \"+<number>\" or "
- "\":<number>\" to jump to the given line number. Append another "
- "\"+<number>\" or \":<number>\" to jump to the column number as well."));
+ setDescription(Tr::tr("Locates files from all project directories. Append \"+<number>\" or "
+ "\":<number>\" to jump to the given line number. Append another "
+ "\"+<number>\" or \":<number>\" to jump to the column number as well."));
+
+ ProjectManager *projectManager = ProjectManager::instance();
+ QTC_ASSERT(projectManager, return);
+ connect(projectManager, &ProjectManager::projectAdded, this, [this](Project *project) {
+ addDirectory(project->projectDirectory());
+ });
+ connect(projectManager, &ProjectManager::projectRemoved, this, [this](Project *project) {
+ removeDirectory(project->projectDirectory());
+ });
}
const char kDirectoriesKey[] = "directories";
@@ -4346,102 +4176,104 @@ void AllProjectFilesFilter::restoreState(const QJsonObject &object)
DirectoryFilter::restoreState(withoutDirectories);
}
-RunConfigurationLocatorFilter::RunConfigurationLocatorFilter()
+static void setupFilter(ILocatorFilter *filter)
{
- connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
- this, &RunConfigurationLocatorFilter::targetListUpdated);
-
- targetListUpdated();
+ QObject::connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged,
+ filter, [filter] { filter->setEnabled(ProjectManager::startupProject()); });
+ filter->setEnabled(ProjectManager::startupProject());
}
-void RunConfigurationLocatorFilter::prepareSearch(const QString &entry)
+using RunAcceptor = std::function<void(RunConfiguration *)>;
+
+static RunConfiguration *runConfigurationForDisplayName(const QString &displayName)
{
- m_result.clear();
- const Target *target = SessionManager::startupTarget();
+ const Target *target = ProjectManager::startupTarget();
if (!target)
- return;
- for (auto rc : target->runConfigurations()) {
- if (rc->displayName().contains(entry, Qt::CaseInsensitive))
- m_result.append(LocatorFilterEntry(this, rc->displayName()));
- }
+ return nullptr;
+ const QList<RunConfiguration *> runconfigs = target->runConfigurations();
+ return Utils::findOrDefault(runconfigs, [displayName](RunConfiguration *rc) {
+ return rc->displayName() == displayName;
+ });
}
-QList<Core::LocatorFilterEntry> RunConfigurationLocatorFilter::matchesFor(
- QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
+static LocatorMatcherTasks runConfigurationMatchers(const RunAcceptor &acceptor)
{
- Q_UNUSED(future)
- Q_UNUSED(entry)
- return m_result;
-}
+ using namespace Tasking;
-void RunConfigurationLocatorFilter::targetListUpdated()
-{
- setEnabled(SessionManager::startupProject()); // at least one project opened
+ TreeStorage<LocatorStorage> storage;
+
+ const auto onSetup = [storage, acceptor] {
+ const QString input = storage->input();
+ const Target *target = ProjectManager::startupTarget();
+ if (!target)
+ return;
+
+ LocatorFilterEntries entries;
+ for (auto rc : target->runConfigurations()) {
+ if (rc->displayName().contains(input, Qt::CaseInsensitive)) {
+ LocatorFilterEntry entry;
+ entry.displayName = rc->displayName();
+ entry.acceptor = [name = entry.displayName, acceptor = acceptor] {
+ RunConfiguration *config = runConfigurationForDisplayName(name);
+ if (!config)
+ return AcceptResult();
+ acceptor(config);
+ return AcceptResult();
+ };
+ entries.append(entry);
+ }
+ }
+ storage->reportOutput(entries);
+ };
+ return {{Sync(onSetup), storage}};
}
-static RunConfiguration *runConfigurationForDisplayName(const QString &displayName)
+static void runAcceptor(RunConfiguration *config)
{
- const Project *project = SessionManager::instance()->startupProject();
- if (!project)
- return nullptr;
- const QList<RunConfiguration *> runconfigs = project->activeTarget()->runConfigurations();
- return Utils::findOrDefault(runconfigs, [displayName](RunConfiguration *rc) {
- return rc->displayName() == displayName;
- });
+ if (!BuildManager::isBuilding(config->project()))
+ ProjectExplorerPlugin::runRunConfiguration(config, Constants::NORMAL_RUN_MODE, true);
}
-RunRunConfigurationLocatorFilter::RunRunConfigurationLocatorFilter()
+RunConfigurationStartFilter::RunConfigurationStartFilter()
{
setId("Run run configuration");
- setDisplayName(Tr::tr("Run run configuration"));
- setDescription(Tr::tr("Run a run configuration of the current active project"));
+ setDisplayName(Tr::tr("Run Run Configuration"));
+ setDescription(Tr::tr("Runs a run configuration of the active project."));
setDefaultShortcutString("rr");
setPriority(Medium);
+ setupFilter(this);
}
-void RunRunConfigurationLocatorFilter::accept(const LocatorFilterEntry &selection, QString *newText,
- int *selectionStart, int *selectionLength) const
+LocatorMatcherTasks RunConfigurationStartFilter::matchers()
{
- Q_UNUSED(newText)
- Q_UNUSED(selectionStart)
- Q_UNUSED(selectionLength)
+ return runConfigurationMatchers(&runAcceptor);
+}
- RunConfiguration *toStart = runConfigurationForDisplayName(selection.displayName);
- if (!toStart)
- return;
- if (!BuildManager::isBuilding(toStart->project()))
- ProjectExplorerPlugin::runRunConfiguration(toStart, Constants::NORMAL_RUN_MODE, true);
+static void switchAcceptor(RunConfiguration *config)
+{
+ ProjectManager::startupTarget()->setActiveRunConfiguration(config);
+ QTimer::singleShot(200, ICore::mainWindow(), [name = config->displayName()] {
+ if (auto ks = ICore::mainWindow()->findChild<QWidget *>("KitSelector.Button")) {
+ ToolTip::show(ks->mapToGlobal(QPoint{25, 25}),
+ Tr::tr("Switched run configuration to\n%1").arg(name),
+ ICore::dialogParent());
+ }
+ });
}
-SwitchToRunConfigurationLocatorFilter::SwitchToRunConfigurationLocatorFilter()
+RunConfigurationSwitchFilter::RunConfigurationSwitchFilter()
{
setId("Switch run configuration");
- setDisplayName(Tr::tr("Switch run configuration"));
- setDescription(Tr::tr("Switch active run configuration"));
+ setDisplayName(Tr::tr("Switch Run Configuration"));
+ setDescription(Tr::tr("Switches the active run configuration of the active project."));
setDefaultShortcutString("sr");
setPriority(Medium);
+ setupFilter(this);
}
-void SwitchToRunConfigurationLocatorFilter::accept(const LocatorFilterEntry &selection,
- QString *newText, int *selectionStart,
- int *selectionLength) const
+LocatorMatcherTasks RunConfigurationSwitchFilter::matchers()
{
- Q_UNUSED(newText)
- Q_UNUSED(selectionStart)
- Q_UNUSED(selectionLength)
-
- RunConfiguration *toSwitchTo = runConfigurationForDisplayName(selection.displayName);
- if (!toSwitchTo)
- return;
-
- SessionManager::startupTarget()->setActiveRunConfiguration(toSwitchTo);
- QTimer::singleShot(200, this, [displayName = selection.displayName] {
- if (auto ks = ICore::mainWindow()->findChild<QWidget *>("KitSelector.Button")) {
- Utils::ToolTip::show(ks->mapToGlobal(QPoint{25, 25}),
- Tr::tr("Switched run configuration to\n%1").arg(displayName),
- ICore::dialogParent());
- }
- });
+ return runConfigurationMatchers(&switchAcceptor);
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index baa8bb83a6..0b87f53310 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -155,7 +155,6 @@ public:
static QThreadPool *sharedThreadPool();
static Internal::MiniProjectTargetSelector *targetSelector();
- static void showSessionManager();
static void openNewProjectDialog();
static void openOpenProjectDialog();
@@ -261,6 +260,9 @@ private slots:
void testProject_projectTree();
void testProject_multipleBuildConfigs();
+ void testSourceToBinaryMapping();
+ void testSourceToBinaryMapping_data();
+
void testSessionSwitch();
#endif // WITH_TESTS
};
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index e65cc1bdc3..c955a48590 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -45,6 +45,7 @@ Project {
"codestylesettingspropertiespage.cpp", "codestylesettingspropertiespage.h",
"compileoutputwindow.cpp", "compileoutputwindow.h",
"configtaskhandler.cpp", "configtaskhandler.h",
+ "copystep.cpp", "copystep.h",
"copytaskhandler.cpp", "copytaskhandler.h",
"currentprojectfilter.cpp", "currentprojectfilter.h",
"currentprojectfind.cpp", "currentprojectfind.h",
@@ -91,7 +92,6 @@ Project {
"ldparser.cpp", "ldparser.h",
"lldparser.cpp", "lldparser.h",
"linuxiccparser.cpp", "linuxiccparser.h",
- "localenvironmentaspect.cpp", "localenvironmentaspect.h",
"makestep.cpp", "makestep.h",
"miniprojecttargetselector.cpp", "miniprojecttargetselector.h",
"msvcparser.cpp", "msvcparser.h",
@@ -110,13 +110,12 @@ Project {
"projectexplorerconstants.cpp",
"projectexplorerconstants.h",
"projectexplorericons.h", "projectexplorericons.cpp",
- "projectexplorersettings.h",
- "projectexplorersettingspage.cpp", "projectexplorersettingspage.h",
+ "projectexplorersettings.h", "projectexplorersettings.cpp",
"projectexplorertr.h",
"projectfilewizardextension.cpp", "projectfilewizardextension.h",
"projectimporter.cpp", "projectimporter.h",
"projectmacro.cpp", "projectmacro.h",
- "projectmanager.h",
+ "projectmanager.cpp", "projectmanager.h",
"projectmodels.cpp", "projectmodels.h",
"projectnodes.cpp", "projectnodes.h",
"projectpanelfactory.cpp", "projectpanelfactory.h",
@@ -134,10 +133,6 @@ Project {
"runsettingspropertiespage.cpp", "runsettingspropertiespage.h",
"sanitizerparser.cpp", "sanitizerparser.h",
"selectablefilesmodel.cpp", "selectablefilesmodel.h",
- "session.cpp", "session.h",
- "sessionmodel.cpp", "sessionmodel.h",
- "sessionview.cpp", "sessionview.h",
- "sessiondialog.cpp", "sessiondialog.h",
"showineditortaskhandler.cpp", "showineditortaskhandler.h",
"showoutputtaskhandler.cpp", "showoutputtaskhandler.h",
"simpleprojectwizard.cpp", "simpleprojectwizard.h",
@@ -226,8 +221,7 @@ Project {
"idevicefactory.cpp", "idevicefactory.h",
"idevicefwd.h",
"idevicewidget.h",
- "localprocesslist.cpp", "localprocesslist.h",
- "sshdeviceprocesslist.cpp", "sshdeviceprocesslist.h",
+ "processlist.cpp", "processlist.h",
"sshparameters.cpp", "sshparameters.h",
"sshsettings.cpp", "sshsettings.h",
"sshsettingspage.cpp", "sshsettingspage.h",
@@ -250,9 +244,7 @@ Project {
]
}
- Group {
- name: "Tests"
- condition: qtc.testsEnabled
+ QtcTestFiles {
files: ["outputparser_test.h", "outputparser_test.cpp"]
}
diff --git a/src/plugins/projectexplorer/projectexplorer.qrc b/src/plugins/projectexplorer/projectexplorer.qrc
index ececb0854b..0cc88e3331 100644
--- a/src/plugins/projectexplorer/projectexplorer.qrc
+++ b/src/plugins/projectexplorer/projectexplorer.qrc
@@ -86,5 +86,13 @@
<file>images/settingscategory_cpp@2x.png</file>
<file>images/importasproject.png</file>
<file>images/importasproject@2x.png</file>
+ <file>testdata/multi-target-project/CMakeLists.txt</file>
+ <file>testdata/multi-target-project/multi-target-project-app.pro</file>
+ <file>testdata/multi-target-project/multi-target-project-lib.cpp</file>
+ <file>testdata/multi-target-project/multi-target-project-lib.pro</file>
+ <file>testdata/multi-target-project/multi-target-project-main.cpp</file>
+ <file>testdata/multi-target-project/multi-target-project-shared.h</file>
+ <file>testdata/multi-target-project/multi-target-project.pro</file>
+ <file>testdata/multi-target-project/multi-target-project.qbs</file>
</qresource>
</RCC>
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index 9c86d6d9cf..75054120a8 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -132,6 +132,10 @@ const char BUILDSTEPS_CLEAN[] = "ProjectExplorer.BuildSteps.Clean";
const char BUILDSTEPS_BUILD[] = "ProjectExplorer.BuildSteps.Build";
const char BUILDSTEPS_DEPLOY[] = "ProjectExplorer.BuildSteps.Deploy";
+const char COPY_FILE_STEP[] = "ProjectExplorer.CopyFileStep";
+const char COPY_DIRECTORY_STEP[] = "ProjectExplorer.CopyDirectoryStep";
+const char DEVICE_CHECK_STEP[] = "ProjectExplorer.DeviceCheckBuildStep";
+
// Language
// Keep these short: These constants are exposed to the MacroExplorer!
@@ -202,8 +206,6 @@ const char FILEOVERLAY_UNKNOWN[]=":/projectexplorer/images/fileoverlay_unknown.p
// Settings
const char ADD_FILES_DIALOG_FILTER_HISTORY_KEY[] = "ProjectExplorer.AddFilesFilterKey";
const char PROJECT_ROOT_PATH_KEY[] = "ProjectExplorer.Project.RootPath";
-const char STARTUPSESSION_KEY[] = "ProjectExplorer/SessionToRestore";
-const char LASTSESSION_KEY[] = "ProjectExplorer/StartupSession";
const char SETTINGS_MENU_HIDE_BUILD[] = "Menu/HideBuild";
const char SETTINGS_MENU_HIDE_DEBUG[] = "Menu/HideDebug";
const char SETTINGS_MENU_HIDE_ANALYZE[] = "Menu/HideAnalyze";
diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.cpp b/src/plugins/projectexplorer/projectexplorersettings.cpp
index 30eb850cd0..14f66b885b 100644
--- a/src/plugins/projectexplorer/projectexplorersettingspage.cpp
+++ b/src/plugins/projectexplorer/projectexplorersettings.cpp
@@ -1,7 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include "projectexplorersettingspage.h"
+#include "projectexplorersettings.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
@@ -25,15 +25,14 @@
using namespace Core;
using namespace Utils;
-namespace ProjectExplorer {
-namespace Internal {
+namespace ProjectExplorer::Internal {
enum { UseCurrentDirectory, UseProjectDirectory };
-class ProjectExplorerSettingsWidget : public QWidget
+class ProjectExplorerSettingsWidget : public IOptionsPageWidget
{
public:
- explicit ProjectExplorerSettingsWidget(QWidget *parent = nullptr);
+ ProjectExplorerSettingsWidget();
ProjectExplorerSettings settings() const;
void setSettings(const ProjectExplorerSettings &s);
@@ -44,6 +43,13 @@ public:
bool useProjectsDirectory();
void setUseProjectsDirectory(bool v);
+ void apply() final
+ {
+ ProjectExplorerPlugin::setProjectExplorerSettings(settings());
+ DocumentManager::setProjectsDirectory(projectsDirectory());
+ DocumentManager::setUseProjectsDirectory(useProjectsDirectory());
+ }
+
private:
void slotDirectoryButtonGroupChanged();
@@ -68,8 +74,7 @@ private:
QButtonGroup *m_directoryButtonGroup;
};
-ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget(QWidget *parent) :
- QWidget(parent)
+ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget()
{
m_currentDirectoryRadioButton = new QRadioButton(Tr::tr("Current directory"));
m_directoryRadioButton = new QRadioButton(Tr::tr("Directory"));
@@ -117,7 +122,7 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget(QWidget *parent) :
"Disable it if you experience problems with your builds.");
jomLabel->setWordWrap(true);
- using namespace Utils::Layouting;
+ using namespace Layouting;
Column {
Group {
title(Tr::tr("Projects Directory")),
@@ -165,6 +170,10 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget(QWidget *parent) :
connect(m_directoryButtonGroup, &QButtonGroup::buttonClicked,
this, &ProjectExplorerSettingsWidget::slotDirectoryButtonGroupChanged);
+
+ setSettings(ProjectExplorerPlugin::projectExplorerSettings());
+ setProjectsDirectory(DocumentManager::projectsDirectory());
+ setUseProjectsDirectory(DocumentManager::useProjectsDirectory());
}
ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const
@@ -236,7 +245,8 @@ void ProjectExplorerSettingsWidget::slotDirectoryButtonGroupChanged()
m_projectsDirectoryPathChooser->setEnabled(enable);
}
-// ------------------ ProjectExplorerSettingsPage
+// ProjectExplorerSettingsPage
+
ProjectExplorerSettingsPage::ProjectExplorerSettingsPage()
{
setId(Constants::BUILD_AND_RUN_SETTINGS_PAGE_ID);
@@ -244,32 +254,7 @@ ProjectExplorerSettingsPage::ProjectExplorerSettingsPage()
setCategory(Constants::BUILD_AND_RUN_SETTINGS_CATEGORY);
setDisplayCategory(Tr::tr("Build & Run"));
setCategoryIconPath(":/projectexplorer/images/settingscategory_buildrun.png");
+ setWidgetCreator([] { return new ProjectExplorerSettingsWidget; });
}
-QWidget *ProjectExplorerSettingsPage::widget()
-{
- if (!m_widget) {
- m_widget = new ProjectExplorerSettingsWidget;
- m_widget->setSettings(ProjectExplorerPlugin::projectExplorerSettings());
- m_widget->setProjectsDirectory(DocumentManager::projectsDirectory());
- m_widget->setUseProjectsDirectory(DocumentManager::useProjectsDirectory());
- }
- return m_widget;
-}
-
-void ProjectExplorerSettingsPage::apply()
-{
- if (m_widget) {
- ProjectExplorerPlugin::setProjectExplorerSettings(m_widget->settings());
- DocumentManager::setProjectsDirectory(m_widget->projectsDirectory());
- DocumentManager::setUseProjectsDirectory(m_widget->useProjectsDirectory());
- }
-}
-
-void ProjectExplorerSettingsPage::finish()
-{
- delete m_widget;
-}
-
-} // namespace Internal
-} // namespace ProjectExplorer
+} // ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h
index b4b80124cd..48cc85c414 100644
--- a/src/plugins/projectexplorer/projectexplorersettings.h
+++ b/src/plugins/projectexplorer/projectexplorersettings.h
@@ -4,6 +4,8 @@
#pragma once
#include <coreplugin/coreconstants.h>
+#include <coreplugin/dialogs/ioptionspage.h>
+
#include <utils/hostosinfo.h>
#include <QUuid>
@@ -23,7 +25,6 @@ public:
&& p1.deployBeforeRun == p2.deployBeforeRun
&& p1.saveBeforeBuild == p2.saveBeforeBuild
&& p1.useJom == p2.useJom
- && p1.autorestoreLastSession == p2.autorestoreLastSession
&& p1.prompToStopRunControl == p2.prompToStopRunControl
&& p1.automaticallyCreateRunConfigurations == p2.automaticallyCreateRunConfigurations
&& p1.addLibraryPathsToRunEnv == p2.addLibraryPathsToRunEnv
@@ -40,7 +41,6 @@ public:
bool deployBeforeRun = true;
bool saveBeforeBuild = false;
bool useJom = true;
- bool autorestoreLastSession = false; // This option is set in the Session Manager!
bool prompToStopRunControl = false;
bool automaticallyCreateRunConfigurations = true;
bool addLibraryPathsToRunEnv = true;
@@ -74,12 +74,10 @@ public:
int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT;
};
-class CompileOutputSettings
+class ProjectExplorerSettingsPage : public Core::IOptionsPage
{
public:
- bool popUp = false;
- bool wrapOutput = false;
- int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT;
+ ProjectExplorerSettingsPage();
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.h b/src/plugins/projectexplorer/projectexplorersettingspage.h
deleted file mode 100644
index 82764c3850..0000000000
--- a/src/plugins/projectexplorer/projectexplorersettingspage.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <coreplugin/dialogs/ioptionspage.h>
-
-#include <QPointer>
-
-namespace ProjectExplorer {
-namespace Internal {
-
-class ProjectExplorerSettingsWidget;
-
-class ProjectExplorerSettingsPage : public Core::IOptionsPage
-{
-public:
- ProjectExplorerSettingsPage();
-
- QWidget *widget() override;
- void apply() override;
- void finish() override;
-
-private:
- QPointer<ProjectExplorerSettingsWidget> m_widget;
-};
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp
index 53d3eb1578..134db6ea48 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.cpp
+++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp
@@ -7,10 +7,10 @@
#include "project.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projectnodes.h"
#include "projecttree.h"
#include "projectwizardpage.h"
-#include "session.h"
#include <coreplugin/icore.h>
@@ -27,7 +27,6 @@
#include <utils/stringutils.h>
#include <QDebug>
-#include <QFileInfo>
#include <QMessageBox>
#include <QPointer>
#include <QTextCursor>
@@ -134,7 +133,7 @@ Node *ProjectFileWizardExtension::findWizardContextNode(Node *contextNode, Proje
const FilePath &path)
{
if (contextNode && !ProjectTree::hasNode(contextNode)) {
- if (SessionManager::projects().contains(project) && project->rootProjectNode()) {
+ if (ProjectManager::projects().contains(project) && project->rootProjectNode()) {
contextNode = project->rootProjectNode()->findNode([path](const Node *n) {
return path == n->filePath();
});
diff --git a/src/plugins/projectexplorer/projectmanager.cpp b/src/plugins/projectexplorer/projectmanager.cpp
new file mode 100644
index 0000000000..e3c8e65c59
--- /dev/null
+++ b/src/plugins/projectexplorer/projectmanager.cpp
@@ -0,0 +1,768 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "projectmanager.h"
+
+
+#include "buildconfiguration.h"
+#include "editorconfiguration.h"
+#include "project.h"
+#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
+#include "projectexplorertr.h"
+#include "projectmanager.h"
+#include "projectnodes.h"
+#include "target.h"
+
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/foldernavigationwidget.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/idocument.h>
+#include <coreplugin/imode.h>
+#include <coreplugin/modemanager.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/session.h>
+
+#include <texteditor/texteditor.h>
+
+#include <utils/algorithm.h>
+#include <utils/filepath.h>
+#include <utils/qtcassert.h>
+#include <utils/stylehelper.h>
+#include <utils/qtcassert.h>
+
+#include <QDebug>
+#include <QMessageBox>
+#include <QPushButton>
+
+#ifdef WITH_TESTS
+#include <QTemporaryFile>
+#include <QTest>
+#include <vector>
+#endif
+
+using namespace Core;
+using namespace Utils;
+using namespace ProjectExplorer::Internal;
+
+namespace ProjectExplorer {
+
+class ProjectManagerPrivate
+{
+public:
+ void loadSession();
+ void saveSession();
+ void restoreDependencies();
+ void restoreStartupProject();
+ void restoreProjects(const FilePaths &fileList);
+ void askUserAboutFailedProjects();
+
+ bool recursiveDependencyCheck(const FilePath &newDep, const FilePath &checkDep) const;
+ FilePaths dependencies(const FilePath &proName) const;
+ FilePaths dependenciesOrder() const;
+ void dependencies(const FilePath &proName, FilePaths &result) const;
+
+ static QString windowTitleAddition(const FilePath &filePath);
+ static QString sessionTitle(const FilePath &filePath);
+
+ bool hasProjects() const { return !m_projects.isEmpty(); }
+
+ bool m_casadeSetActive = false;
+
+ Project *m_startupProject = nullptr;
+ QList<Project *> m_projects;
+ FilePaths m_failedProjects;
+ QMap<FilePath, FilePaths> m_depMap;
+
+private:
+ static QString locationInProject(const FilePath &filePath);
+};
+
+static ProjectManager *m_instance = nullptr;
+static ProjectManagerPrivate *d = nullptr;
+
+static QString projectFolderId(Project *pro)
+{
+ return pro->projectFilePath().toString();
+}
+
+const int PROJECT_SORT_VALUE = 100;
+
+ProjectManager::ProjectManager()
+{
+ m_instance = this;
+ d = new ProjectManagerPrivate;
+
+ connect(EditorManager::instance(), &EditorManager::editorCreated,
+ this, &ProjectManager::configureEditor);
+ connect(this, &ProjectManager::projectAdded,
+ EditorManager::instance(), &EditorManager::updateWindowTitles);
+ connect(this, &ProjectManager::projectRemoved,
+ EditorManager::instance(), &EditorManager::updateWindowTitles);
+ connect(this, &ProjectManager::projectDisplayNameChanged,
+ EditorManager::instance(), &EditorManager::updateWindowTitles);
+
+ EditorManager::setWindowTitleAdditionHandler(&ProjectManagerPrivate::windowTitleAddition);
+ EditorManager::setSessionTitleHandler(&ProjectManagerPrivate::sessionTitle);
+
+ connect(SessionManager::instance(), &SessionManager::aboutToLoadSession, this, [] {
+ d->loadSession();
+ });
+ connect(SessionManager::instance(), &SessionManager::aboutToSaveSession, this, [] {
+ d->saveSession();
+ });
+}
+
+ProjectManager::~ProjectManager()
+{
+ EditorManager::setWindowTitleAdditionHandler({});
+ EditorManager::setSessionTitleHandler({});
+ delete d;
+ d = nullptr;
+}
+
+ProjectManager *ProjectManager::instance()
+{
+ return m_instance;
+}
+
+bool ProjectManagerPrivate::recursiveDependencyCheck(const FilePath &newDep,
+ const FilePath &checkDep) const
+{
+ if (newDep == checkDep)
+ return false;
+
+ const FilePaths depList = m_depMap.value(checkDep);
+ for (const FilePath &dependency : depList) {
+ if (!recursiveDependencyCheck(newDep, dependency))
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * The dependency management exposes an interface based on projects, but
+ * is internally purely string based. This is suboptimal. Probably it would be
+ * nicer to map the filenames to projects on load and only map it back to
+ * filenames when saving.
+ */
+
+QList<Project *> ProjectManager::dependencies(const Project *project)
+{
+ const FilePath proName = project->projectFilePath();
+ const FilePaths proDeps = d->m_depMap.value(proName);
+
+ QList<Project *> projects;
+ for (const FilePath &dep : proDeps) {
+ Project *pro = Utils::findOrDefault(d->m_projects, [&dep](Project *p) {
+ return p->projectFilePath() == dep;
+ });
+ if (pro)
+ projects += pro;
+ }
+
+ return projects;
+}
+
+bool ProjectManager::hasDependency(const Project *project, const Project *depProject)
+{
+ const FilePath proName = project->projectFilePath();
+ const FilePath depName = depProject->projectFilePath();
+
+ const FilePaths proDeps = d->m_depMap.value(proName);
+ return proDeps.contains(depName);
+}
+
+bool ProjectManager::canAddDependency(const Project *project, const Project *depProject)
+{
+ const FilePath newDep = project->projectFilePath();
+ const FilePath checkDep = depProject->projectFilePath();
+
+ return d->recursiveDependencyCheck(newDep, checkDep);
+}
+
+bool ProjectManager::addDependency(Project *project, Project *depProject)
+{
+ const FilePath proName = project->projectFilePath();
+ const FilePath depName = depProject->projectFilePath();
+
+ // check if this dependency is valid
+ if (!d->recursiveDependencyCheck(proName, depName))
+ return false;
+
+ FilePaths proDeps = d->m_depMap.value(proName);
+ if (!proDeps.contains(depName)) {
+ proDeps.append(depName);
+ d->m_depMap[proName] = proDeps;
+ }
+ emit m_instance->dependencyChanged(project, depProject);
+
+ return true;
+}
+
+void ProjectManager::removeDependency(Project *project, Project *depProject)
+{
+ const FilePath proName = project->projectFilePath();
+ const FilePath depName = depProject->projectFilePath();
+
+ FilePaths proDeps = d->m_depMap.value(proName);
+ proDeps.removeAll(depName);
+ if (proDeps.isEmpty())
+ d->m_depMap.remove(proName);
+ else
+ d->m_depMap[proName] = proDeps;
+ emit m_instance->dependencyChanged(project, depProject);
+}
+
+bool ProjectManager::isProjectConfigurationCascading()
+{
+ return d->m_casadeSetActive;
+}
+
+void ProjectManager::setProjectConfigurationCascading(bool b)
+{
+ d->m_casadeSetActive = b;
+ SessionManager::markSessionFileDirty();
+}
+
+void ProjectManager::setStartupProject(Project *startupProject)
+{
+ QTC_ASSERT((!startupProject && d->m_projects.isEmpty())
+ || (startupProject && d->m_projects.contains(startupProject)), return);
+
+ if (d->m_startupProject == startupProject)
+ return;
+
+ d->m_startupProject = startupProject;
+ if (d->m_startupProject && d->m_startupProject->needsConfiguration()) {
+ ModeManager::activateMode(Constants::MODE_SESSION);
+ ModeManager::setFocusToCurrentMode();
+ }
+ FolderNavigationWidgetFactory::setFallbackSyncFilePath(
+ startupProject ? startupProject->projectFilePath().parentDir() : FilePath());
+ emit m_instance->startupProjectChanged(startupProject);
+}
+
+Project *ProjectManager::startupProject()
+{
+ return d->m_startupProject;
+}
+
+Target *ProjectManager::startupTarget()
+{
+ return d->m_startupProject ? d->m_startupProject->activeTarget() : nullptr;
+}
+
+BuildSystem *ProjectManager::startupBuildSystem()
+{
+ Target *t = startupTarget();
+ return t ? t->buildSystem() : nullptr;
+}
+
+/*!
+ * Returns the RunConfiguration of the currently active target
+ * of the startup project, if such exists, or \c nullptr otherwise.
+ */
+
+
+RunConfiguration *ProjectManager::startupRunConfiguration()
+{
+ Target *t = startupTarget();
+ return t ? t->activeRunConfiguration() : nullptr;
+}
+
+void ProjectManager::addProject(Project *pro)
+{
+ QTC_ASSERT(pro, return);
+ QTC_CHECK(!pro->displayName().isEmpty());
+ QTC_CHECK(pro->id().isValid());
+
+ SessionManager::markSessionFileDirty();
+ QTC_ASSERT(!d->m_projects.contains(pro), return);
+
+ d->m_projects.append(pro);
+
+ connect(pro, &Project::displayNameChanged,
+ m_instance, [pro]() { emit m_instance->projectDisplayNameChanged(pro); });
+
+ emit m_instance->projectAdded(pro);
+ const auto updateFolderNavigation = [pro] {
+ // destructing projects might trigger changes, so check if the project is actually there
+ if (QTC_GUARD(d->m_projects.contains(pro))) {
+ const QIcon icon = pro->rootProjectNode() ? pro->rootProjectNode()->icon() : QIcon();
+ FolderNavigationWidgetFactory::insertRootDirectory({projectFolderId(pro),
+ PROJECT_SORT_VALUE,
+ pro->displayName(),
+ pro->projectFilePath().parentDir(),
+ icon});
+ }
+ };
+ updateFolderNavigation();
+ configureEditors(pro);
+ connect(pro, &Project::fileListChanged, m_instance, [pro, updateFolderNavigation]() {
+ configureEditors(pro);
+ updateFolderNavigation(); // update icon
+ });
+ connect(pro, &Project::displayNameChanged, m_instance, updateFolderNavigation);
+
+ if (!startupProject())
+ setStartupProject(pro);
+}
+
+void ProjectManager::removeProject(Project *project)
+{
+ SessionManager::markSessionFileDirty();
+ QTC_ASSERT(project, return);
+ removeProjects({project});
+}
+
+void ProjectManagerPrivate::saveSession()
+{
+ // save the startup project
+ if (d->m_startupProject)
+ SessionManager::setSessionValue("StartupProject",
+ m_startupProject->projectFilePath().toSettings());
+
+ FilePaths projectFiles = Utils::transform(m_projects, &Project::projectFilePath);
+ // Restore information on projects that failed to load:
+ // don't read projects to the list, which the user loaded
+ for (const FilePath &failed : std::as_const(m_failedProjects)) {
+ if (!projectFiles.contains(failed))
+ projectFiles << failed;
+ }
+
+ SessionManager::setSessionValue("ProjectList",
+ Utils::transform<QStringList>(projectFiles,
+ &FilePath::toString));
+ SessionManager::setSessionValue("CascadeSetActive", m_casadeSetActive);
+
+ QVariantMap depMap;
+ auto i = m_depMap.constBegin();
+ while (i != m_depMap.constEnd()) {
+ QString key = i.key().toString();
+ QStringList values;
+ const FilePaths valueList = i.value();
+ for (const FilePath &value : valueList)
+ values << value.toString();
+ depMap.insert(key, values);
+ ++i;
+ }
+ SessionManager::setSessionValue(QLatin1String("ProjectDependencies"), QVariant(depMap));
+}
+
+/*!
+ Closes all projects
+ */
+void ProjectManager::closeAllProjects()
+{
+ removeProjects(projects());
+}
+
+const QList<Project *> ProjectManager::projects()
+{
+ return d->m_projects;
+}
+
+bool ProjectManager::hasProjects()
+{
+ return d->hasProjects();
+}
+
+bool ProjectManager::hasProject(Project *p)
+{
+ return d->m_projects.contains(p);
+}
+
+FilePaths ProjectManagerPrivate::dependencies(const FilePath &proName) const
+{
+ FilePaths result;
+ dependencies(proName, result);
+ return result;
+}
+
+void ProjectManagerPrivate::dependencies(const FilePath &proName, FilePaths &result) const
+{
+ const FilePaths depends = m_depMap.value(proName);
+
+ for (const FilePath &dep : depends)
+ dependencies(dep, result);
+
+ if (!result.contains(proName))
+ result.append(proName);
+}
+
+QString ProjectManagerPrivate::sessionTitle(const FilePath &filePath)
+{
+ const QString sessionName = SessionManager::activeSession();
+ if (SessionManager::isDefaultSession(sessionName)) {
+ if (filePath.isEmpty()) {
+ // use single project's name if there is only one loaded.
+ const QList<Project *> projects = ProjectManager::projects();
+ if (projects.size() == 1)
+ return projects.first()->displayName();
+ }
+ } else {
+ return sessionName.isEmpty() ? Tr::tr("Untitled") : sessionName;
+ }
+ return QString();
+}
+
+QString ProjectManagerPrivate::locationInProject(const FilePath &filePath)
+{
+ const Project *project = ProjectManager::projectForFile(filePath);
+ if (!project)
+ return QString();
+
+ const FilePath parentDir = filePath.parentDir();
+ if (parentDir == project->projectDirectory())
+ return "@ " + project->displayName();
+
+ if (filePath.isChildOf(project->projectDirectory())) {
+ const FilePath dirInProject = parentDir.relativeChildPath(project->projectDirectory());
+ return "(" + dirInProject.toUserOutput() + " @ " + project->displayName() + ")";
+ }
+
+ // For a file that is "outside" the project it belongs to, we display its
+ // dir's full path because it is easier to read than a series of "../../.".
+ // Example: /home/hugo/GenericProject/App.files lists /home/hugo/lib/Bar.cpp
+ return "(" + parentDir.toUserOutput() + " @ " + project->displayName() + ")";
+}
+
+QString ProjectManagerPrivate::windowTitleAddition(const FilePath &filePath)
+{
+ return filePath.isEmpty() ? QString() : locationInProject(filePath);
+}
+
+FilePaths ProjectManagerPrivate::dependenciesOrder() const
+{
+ QList<QPair<FilePath, FilePaths>> unordered;
+ FilePaths ordered;
+
+ // copy the map to a temporary list
+ for (const Project *pro : m_projects) {
+ const FilePath proName = pro->projectFilePath();
+ const FilePaths depList = filtered(m_depMap.value(proName),
+ [this](const FilePath &proPath) {
+ return contains(m_projects, [proPath](const Project *p) {
+ return p->projectFilePath() == proPath;
+ });
+ });
+ unordered.push_back({proName, depList});
+ }
+
+ while (!unordered.isEmpty()) {
+ for (int i = (unordered.count() - 1); i >= 0; --i) {
+ if (unordered.at(i).second.isEmpty()) {
+ ordered << unordered.at(i).first;
+ unordered.removeAt(i);
+ }
+ }
+
+ // remove the handled projects from the dependency lists
+ // of the remaining unordered projects
+ for (int i = 0; i < unordered.count(); ++i) {
+ for (const FilePath &pro : std::as_const(ordered)) {
+ FilePaths depList = unordered.at(i).second;
+ depList.removeAll(pro);
+ unordered[i].second = depList;
+ }
+ }
+ }
+
+ return ordered;
+}
+
+QList<Project *> ProjectManager::projectOrder(const Project *project)
+{
+ QList<Project *> result;
+
+ FilePaths pros;
+ if (project)
+ pros = d->dependencies(project->projectFilePath());
+ else
+ pros = d->dependenciesOrder();
+
+ for (const FilePath &proFile : std::as_const(pros)) {
+ for (Project *pro : projects()) {
+ if (pro->projectFilePath() == proFile) {
+ result << pro;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+Project *ProjectManager::projectForFile(const FilePath &fileName)
+{
+ if (Project * const project = Utils::findOrDefault(ProjectManager::projects(),
+ [&fileName](const Project *p) { return p->isKnownFile(fileName); })) {
+ return project;
+ }
+ return Utils::findOrDefault(ProjectManager::projects(),
+ [&fileName](const Project *p) {
+ for (const Target * const target : p->targets()) {
+ for (const BuildConfiguration * const bc : target->buildConfigurations()) {
+ if (fileName.isChildOf(bc->buildDirectory()))
+ return false;
+ }
+ }
+ return fileName.isChildOf(p->projectDirectory());
+ });
+}
+
+Project *ProjectManager::projectWithProjectFilePath(const FilePath &filePath)
+{
+ return Utils::findOrDefault(ProjectManager::projects(),
+ [&filePath](const Project *p) { return p->projectFilePath() == filePath; });
+}
+
+void ProjectManager::configureEditor(IEditor *editor, const QString &fileName)
+{
+ if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) {
+ Project *project = projectForFile(Utils::FilePath::fromString(fileName));
+ // Global settings are the default.
+ if (project)
+ project->editorConfiguration()->configureEditor(textEditor);
+ }
+}
+
+void ProjectManager::configureEditors(Project *project)
+{
+ const QList<IDocument *> documents = DocumentModel::openedDocuments();
+ for (IDocument *document : documents) {
+ if (project->isKnownFile(document->filePath())) {
+ const QList<IEditor *> editors = DocumentModel::editorsForDocument(document);
+ for (IEditor *editor : editors) {
+ if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) {
+ project->editorConfiguration()->configureEditor(textEditor);
+ }
+ }
+ }
+ }
+}
+
+void ProjectManager::removeProjects(const QList<Project *> &remove)
+{
+ for (Project *pro : remove)
+ emit m_instance->aboutToRemoveProject(pro);
+
+ bool changeStartupProject = false;
+
+ // Delete projects
+ for (Project *pro : remove) {
+ pro->saveSettings();
+ pro->markAsShuttingDown();
+
+ // Remove the project node:
+ d->m_projects.removeOne(pro);
+
+ if (pro == d->m_startupProject)
+ changeStartupProject = true;
+
+ FolderNavigationWidgetFactory::removeRootDirectory(projectFolderId(pro));
+ disconnect(pro, nullptr, m_instance, nullptr);
+ emit m_instance->projectRemoved(pro);
+ }
+
+ if (changeStartupProject)
+ setStartupProject(hasProjects() ? projects().first() : nullptr);
+
+ qDeleteAll(remove);
+}
+
+void ProjectManagerPrivate::restoreDependencies()
+{
+ QMap<QString, QVariant> depMap = SessionManager::sessionValue("ProjectDependencies").toMap();
+ auto i = depMap.constBegin();
+ while (i != depMap.constEnd()) {
+ const QString &key = i.key();
+ FilePaths values;
+ const QStringList valueList = i.value().toStringList();
+ for (const QString &value : valueList)
+ values << FilePath::fromString(value);
+ m_depMap.insert(FilePath::fromString(key), values);
+ ++i;
+ }
+}
+
+void ProjectManagerPrivate::askUserAboutFailedProjects()
+{
+ FilePaths failedProjects = m_failedProjects;
+ if (!failedProjects.isEmpty()) {
+ QString fileList = FilePath::formatFilePaths(failedProjects, "<br>");
+ QMessageBox box(QMessageBox::Warning,
+ Tr::tr("Failed to restore project files"),
+ Tr::tr("Could not restore the following project files:<br><b>%1</b>").
+ arg(fileList));
+ auto keepButton = new QPushButton(Tr::tr("Keep projects in Session"), &box);
+ auto removeButton = new QPushButton(Tr::tr("Remove projects from Session"), &box);
+ box.addButton(keepButton, QMessageBox::AcceptRole);
+ box.addButton(removeButton, QMessageBox::DestructiveRole);
+
+ box.exec();
+
+ if (box.clickedButton() == removeButton)
+ m_failedProjects.clear();
+ }
+}
+
+void ProjectManagerPrivate::restoreStartupProject()
+{
+ const FilePath startupProject = FilePath::fromSettings(
+ SessionManager::sessionValue("StartupProject"));
+ if (!startupProject.isEmpty()) {
+ for (Project *pro : std::as_const(m_projects)) {
+ if (pro->projectFilePath() == startupProject) {
+ m_instance->setStartupProject(pro);
+ break;
+ }
+ }
+ }
+ if (!m_startupProject) {
+ if (!startupProject.isEmpty())
+ qWarning() << "Could not find startup project" << startupProject;
+ if (hasProjects())
+ m_instance->setStartupProject(m_projects.first());
+ }
+}
+
+/*!
+ Loads a session, takes a session name (not filename).
+*/
+void ProjectManagerPrivate::restoreProjects(const FilePaths &fileList)
+{
+ // indirectly adds projects to session
+ // Keep projects that failed to load in the session!
+ m_failedProjects = fileList;
+ if (!fileList.isEmpty()) {
+ ProjectExplorerPlugin::OpenProjectResult result = ProjectExplorerPlugin::openProjects(fileList);
+ if (!result)
+ ProjectExplorerPlugin::showOpenProjectError(result);
+ const QList<Project *> projects = result.projects();
+ for (const Project *p : projects)
+ m_failedProjects.removeAll(p->projectFilePath());
+ }
+}
+
+void ProjectManagerPrivate::loadSession()
+{
+ d->m_failedProjects.clear();
+ d->m_depMap.clear();
+ d->m_casadeSetActive = false;
+
+ // not ideal that this is in ProjectManager
+ Id modeId = Id::fromSetting(SessionManager::value(QLatin1String("ActiveMode")));
+ if (!modeId.isValid())
+ modeId = Id(Core::Constants::MODE_EDIT);
+
+ // find a list of projects to close later
+ const FilePaths fileList = FileUtils::toFilePathList(
+ SessionManager::sessionValue("ProjectList").toStringList());
+ const QList<Project *> projectsToRemove
+ = Utils::filtered(ProjectManager::projects(), [&fileList](Project *p) {
+ return !fileList.contains(p->projectFilePath());
+ });
+ const QList<Project *> openProjects = ProjectManager::projects();
+ const FilePaths projectPathsToLoad
+ = Utils::filtered(fileList, [&openProjects](const FilePath &path) {
+ return !Utils::contains(openProjects,
+ [&path](Project *p) { return p->projectFilePath() == path; });
+ });
+
+ SessionManager::addSessionLoadingSteps(projectPathsToLoad.count());
+
+ d->restoreProjects(projectPathsToLoad);
+ d->restoreDependencies();
+ d->restoreStartupProject();
+
+ // only remove old projects now that the startup project is set!
+ ProjectManager::removeProjects(projectsToRemove);
+
+ // Fall back to Project mode if the startup project is unconfigured and
+ // use the mode saved in the session otherwise
+ if (d->m_startupProject && d->m_startupProject->needsConfiguration())
+ modeId = Id(Constants::MODE_SESSION);
+
+ ModeManager::activateMode(modeId);
+ ModeManager::setFocusToCurrentMode();
+
+ d->m_casadeSetActive = SessionManager::sessionValue("CascadeSetActive", false).toBool();
+
+ // Starts a event loop, better do that at the very end
+ QMetaObject::invokeMethod(m_instance, [this] { askUserAboutFailedProjects(); });
+}
+
+FilePaths ProjectManager::projectsForSessionName(const QString &session)
+{
+ const FilePath fileName = SessionManager::sessionNameToFileName(session);
+ PersistentSettingsReader reader;
+ if (fileName.exists()) {
+ if (!reader.load(fileName)) {
+ qWarning() << "Could not restore session" << fileName.toUserOutput();
+ return {};
+ }
+ }
+ return transform(reader.restoreValue(QLatin1String("ProjectList")).toStringList(),
+ &FilePath::fromUserInput);
+}
+
+#ifdef WITH_TESTS
+
+void ProjectExplorerPlugin::testSessionSwitch()
+{
+ QVERIFY(SessionManager::createSession("session1"));
+ QVERIFY(SessionManager::createSession("session2"));
+ QTemporaryFile cppFile("main.cpp");
+ QVERIFY(cppFile.open());
+ cppFile.close();
+ QTemporaryFile projectFile1("XXXXXX.pro");
+ QTemporaryFile projectFile2("XXXXXX.pro");
+ struct SessionSpec {
+ SessionSpec(const QString &n, QTemporaryFile &f) : name(n), projectFile(f) {}
+ const QString name;
+ QTemporaryFile &projectFile;
+ };
+ std::vector<SessionSpec> sessionSpecs{SessionSpec("session1", projectFile1),
+ SessionSpec("session2", projectFile2)};
+ for (const SessionSpec &sessionSpec : sessionSpecs) {
+ static const QByteArray proFileContents
+ = "TEMPLATE = app\n"
+ "CONFIG -= qt\n"
+ "SOURCES = " + cppFile.fileName().toLocal8Bit();
+ QVERIFY(sessionSpec.projectFile.open());
+ sessionSpec.projectFile.write(proFileContents);
+ sessionSpec.projectFile.close();
+ QVERIFY(SessionManager::loadSession(sessionSpec.name));
+ const OpenProjectResult openResult
+ = ProjectExplorerPlugin::openProject(
+ FilePath::fromString(sessionSpec.projectFile.fileName()));
+ if (openResult.errorMessage().contains("text/plain"))
+ QSKIP("This test requires the presence of QmakeProjectManager to be fully functional");
+ QVERIFY(openResult);
+ QCOMPARE(openResult.projects().count(), 1);
+ QVERIFY(openResult.project());
+ QCOMPARE(ProjectManager::projects().count(), 1);
+ }
+ for (int i = 0; i < 30; ++i) {
+ QVERIFY(SessionManager::loadSession("session1"));
+ QCOMPARE(SessionManager::activeSession(), "session1");
+ QCOMPARE(ProjectManager::projects().count(), 1);
+ QVERIFY(SessionManager::loadSession("session2"));
+ QCOMPARE(SessionManager::activeSession(), "session2");
+ QCOMPARE(ProjectManager::projects().count(), 1);
+ }
+ QVERIFY(SessionManager::loadSession("session1"));
+ ProjectManager::closeAllProjects();
+ QVERIFY(SessionManager::loadSession("session2"));
+ ProjectManager::closeAllProjects();
+ QVERIFY(SessionManager::deleteSession("session1"));
+ QVERIFY(SessionManager::deleteSession("session2"));
+}
+
+#endif // WITH_TESTS
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectmanager.h b/src/plugins/projectexplorer/projectmanager.h
index 9d54eba572..f49cc96e54 100644
--- a/src/plugins/projectexplorer/projectmanager.h
+++ b/src/plugins/projectexplorer/projectmanager.h
@@ -6,20 +6,35 @@
#include "projectexplorer_export.h"
#include <QString>
+#include <QObject>
+
+namespace Core { class IEditor; }
#include <functional>
namespace Utils {
class FilePath;
+using FilePaths = QList<FilePath>;
class MimeType;
} // Utils
namespace ProjectExplorer {
+class BuildSystem;
class Project;
+class RunConfiguration;
+class Target;
-class PROJECTEXPLORER_EXPORT ProjectManager
+class PROJECTEXPLORER_EXPORT ProjectManager : public QObject
{
+ Q_OBJECT
+
+public:
+ ProjectManager();
+ ~ProjectManager() override;
+
+ static ProjectManager *instance();
+
public:
static bool canOpenProjectForMimeType(const Utils::MimeType &mt);
static Project *openProject(const Utils::MimeType &mt, const Utils::FilePath &fileName);
@@ -32,7 +47,59 @@ public:
});
}
+ static void closeAllProjects();
+
+ static void addProject(Project *project);
+ static void removeProject(Project *project);
+ static void removeProjects(const QList<Project *> &remove);
+
+ static void setStartupProject(Project *startupProject);
+
+ static QList<Project *> dependencies(const Project *project);
+ static bool hasDependency(const Project *project, const Project *depProject);
+ static bool canAddDependency(const Project *project, const Project *depProject);
+ static bool addDependency(Project *project, Project *depProject);
+ static void removeDependency(Project *project, Project *depProject);
+
+ static bool isProjectConfigurationCascading();
+ static void setProjectConfigurationCascading(bool b);
+
+ static Project *startupProject();
+ static Target *startupTarget();
+ static BuildSystem *startupBuildSystem();
+ static RunConfiguration *startupRunConfiguration();
+
+ static const QList<Project *> projects();
+ static bool hasProjects();
+ static bool hasProject(Project *p);
+
+ // NBS rewrite projectOrder (dependency management)
+ static QList<Project *> projectOrder(const Project *project = nullptr);
+
+ static Project *projectForFile(const Utils::FilePath &fileName);
+ static Project *projectWithProjectFilePath(const Utils::FilePath &filePath);
+
+ static Utils::FilePaths projectsForSessionName(const QString &session);
+
+signals:
+ void targetAdded(ProjectExplorer::Target *target);
+ void targetRemoved(ProjectExplorer::Target *target);
+ void projectAdded(ProjectExplorer::Project *project);
+ void aboutToRemoveProject(ProjectExplorer::Project *project);
+ void projectDisplayNameChanged(ProjectExplorer::Project *project);
+ void projectRemoved(ProjectExplorer::Project *project);
+
+ void startupProjectChanged(ProjectExplorer::Project *project);
+
+ void dependencyChanged(ProjectExplorer::Project *a, ProjectExplorer::Project *b);
+
+ // for tests only
+ void projectFinishedParsing(ProjectExplorer::Project *project);
+
private:
+ static void configureEditor(Core::IEditor *editor, const QString &fileName);
+ static void configureEditors(Project *project);
+
static void registerProjectCreator(const QString &mimeType,
const std::function<Project *(const Utils::FilePath &)> &);
};
diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
index 0a761f91e6..9805e654b7 100644
--- a/src/plugins/projectexplorer/projectmodels.cpp
+++ b/src/plugins/projectexplorer/projectmodels.cpp
@@ -8,8 +8,8 @@
#include "projectnodes.h"
#include "projectexplorer.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projecttree.h"
-#include "session.h"
#include "target.h"
#include <app/app_version.h>
@@ -17,6 +17,7 @@
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/iversioncontrol.h>
+#include <coreplugin/session.h>
#include <coreplugin/vcsmanager.h>
#include <utils/utilsicons.h>
@@ -24,8 +25,8 @@
#include <utils/dropsupport.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/pathchooser.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <utils/theme/theme.h>
@@ -174,14 +175,15 @@ FlatModel::FlatModel(QObject *parent)
ProjectTree *tree = ProjectTree::instance();
connect(tree, &ProjectTree::subtreeChanged, this, &FlatModel::updateSubtree);
- SessionManager *sm = SessionManager::instance();
- connect(sm, &SessionManager::projectRemoved, this, &FlatModel::handleProjectRemoved);
- connect(sm, &SessionManager::aboutToLoadSession, this, &FlatModel::loadExpandData);
- connect(sm, &SessionManager::aboutToSaveSession, this, &FlatModel::saveExpandData);
- connect(sm, &SessionManager::projectAdded, this, &FlatModel::handleProjectAdded);
- connect(sm, &SessionManager::startupProjectChanged, this, [this] { emit layoutChanged(); });
+ ProjectManager *sm = ProjectManager::instance();
+ SessionManager *sb = SessionManager::instance();
+ connect(sm, &ProjectManager::projectRemoved, this, &FlatModel::handleProjectRemoved);
+ connect(sb, &SessionManager::aboutToLoadSession, this, &FlatModel::loadExpandData);
+ connect(sb, &SessionManager::aboutToSaveSession, this, &FlatModel::saveExpandData);
+ connect(sm, &ProjectManager::projectAdded, this, &FlatModel::handleProjectAdded);
+ connect(sm, &ProjectManager::startupProjectChanged, this, [this] { emit layoutChanged(); });
- for (Project *project : SessionManager::projects())
+ for (Project *project : ProjectManager::projects())
handleProjectAdded(project);
}
@@ -234,7 +236,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
}
case Qt::FontRole: {
QFont font;
- if (project == SessionManager::startupProject())
+ if (project == ProjectManager::startupProject())
font.setBold(true);
return font;
}
@@ -407,7 +409,7 @@ void FlatModel::updateSubtree(FolderNode *node)
void FlatModel::rebuildModel()
{
- const QList<Project *> projects = SessionManager::projects();
+ const QList<Project *> projects = ProjectManager::projects();
for (Project *project : projects)
addOrRebuildProjectModel(project);
}
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index 10699b7d90..e5c8a9a3c6 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -326,14 +326,13 @@ FilePath Node::pathOrDirectory(bool dir) const
FilePath location;
// Virtual Folder case
// If there are files directly below or no subfolders, take the folder path
- if (!folder->fileNodes().isEmpty() || folder->folderNodes().isEmpty()) {
+ auto Any = [](auto) { return true; };
+ if (folder->findChildFileNode(Any) || !folder->findChildFolderNode(Any)) {
location = m_filePath;
} else {
// Otherwise we figure out a commonPath from the subfolders
FilePaths list;
- const QList<FolderNode *> folders = folder->folderNodes();
- for (FolderNode *f : folders)
- list << f->filePath();
+ folder->forEachFolderNode([&](FolderNode *f) { list << f->filePath(); });
location = FileUtils::commonPath(list);
}
@@ -547,6 +546,22 @@ void FolderNode::forEachProjectNode(const std::function<void(const ProjectNode *
}
}
+void FolderNode::forEachFileNode(const std::function<void (FileNode *)> &fileTask) const
+{
+ for (const std::unique_ptr<Node> &n : m_nodes) {
+ if (FileNode *fn = n->asFileNode())
+ fileTask(fn);
+ }
+}
+
+void FolderNode::forEachFolderNode(const std::function<void (FolderNode *)> &folderTask) const
+{
+ for (const std::unique_ptr<Node> &n : m_nodes) {
+ if (FolderNode *fn = n->asFolderNode())
+ folderTask(fn);
+ }
+}
+
ProjectNode *FolderNode::findProjectNode(const std::function<bool(const ProjectNode *)> &predicate)
{
if (ProjectNode *projectNode = asProjectNode()) {
@@ -563,19 +578,29 @@ ProjectNode *FolderNode::findProjectNode(const std::function<bool(const ProjectN
return nullptr;
}
-const QList<Node *> FolderNode::nodes() const
+FolderNode *FolderNode::findChildFolderNode(const std::function<bool(FolderNode *)> &predicate) const
{
- return Utils::toRawPointer<QList>(m_nodes);
+ for (const std::unique_ptr<Node> &n : m_nodes) {
+ if (FolderNode *fn = n->asFolderNode())
+ if (predicate(fn))
+ return fn;
+ }
+ return nullptr;
}
-QList<FileNode *> FolderNode::fileNodes() const
+FileNode *FolderNode::findChildFileNode(const std::function<bool(FileNode *)> &predicate) const
{
- QList<FileNode *> result;
for (const std::unique_ptr<Node> &n : m_nodes) {
if (FileNode *fn = n->asFileNode())
- result.append(fn);
+ if (predicate(fn))
+ return fn;
}
- return result;
+ return nullptr;
+}
+
+const QList<Node *> FolderNode::nodes() const
+{
+ return Utils::toRawPointer<QList>(m_nodes);
}
FileNode *FolderNode::fileNode(const Utils::FilePath &file) const
@@ -587,16 +612,6 @@ FileNode *FolderNode::fileNode(const Utils::FilePath &file) const
}));
}
-QList<FolderNode *> FolderNode::folderNodes() const
-{
- QList<FolderNode *> result;
- for (const std::unique_ptr<Node> &n : m_nodes) {
- if (FolderNode *fn = n->asFolderNode())
- result.append(fn);
- }
- return result;
-}
-
FolderNode *FolderNode::folderNode(const Utils::FilePath &directory) const
{
Node *node = Utils::findOrDefault(m_nodes, [directory](const std::unique_ptr<Node> &n) {
@@ -669,8 +684,7 @@ void FolderNode::compress()
compress();
} else {
- for (FolderNode *fn : folderNodes())
- fn->compress();
+ forEachFolderNode([&](FolderNode *fn) { fn->compress(); });
}
}
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index 35927c02c8..0e0068ba7b 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -32,6 +32,8 @@ enum class FileType : quint16 {
Resource,
QML,
Project,
+ App,
+ Lib,
FileTypeSize
};
@@ -228,11 +230,13 @@ public:
const std::function<bool(const FolderNode *)> &folderFilterTask = {}) const;
void forEachGenericNode(const std::function<void(Node *)> &genericTask) const;
void forEachProjectNode(const std::function<void(const ProjectNode *)> &genericTask) const;
- ProjectNode *findProjectNode(const std::function<bool(const ProjectNode *)> &predicate);
+ void forEachFileNode(const std::function<void(FileNode *)> &fileTask) const;
+ void forEachFolderNode(const std::function<void(FolderNode *)> &folderTask) const;
+ ProjectNode *findProjectNode(const std::function<bool(const ProjectNode *)> &predicate); // recursive
+ FolderNode *findChildFolderNode(const std::function<bool (FolderNode *)> &predicate) const; // non-recursive
+ FileNode *findChildFileNode(const std::function<bool (FileNode *)> &predicate) const; // non-recursive
const QList<Node *> nodes() const;
- QList<FileNode *> fileNodes() const;
FileNode *fileNode(const Utils::FilePath &file) const;
- QList<FolderNode *> folderNodes() const;
FolderNode *folderNode(const Utils::FilePath &directory) const;
using FolderNodeFactory = std::function<std::unique_ptr<FolderNode>(const Utils::FilePath &)>;
diff --git a/src/plugins/projectexplorer/projectnodeshelper.h b/src/plugins/projectexplorer/projectnodeshelper.h
index 727497c6bf..bcb5454fd8 100644
--- a/src/plugins/projectexplorer/projectnodeshelper.h
+++ b/src/plugins/projectexplorer/projectnodeshelper.h
@@ -11,18 +11,19 @@
#include <utils/algorithm.h>
#include <utils/filepath.h>
+#include <QPromise>
+
namespace ProjectExplorer {
template<typename Result>
-QList<FileNode *> scanForFiles(QFutureInterface<Result> &future,
- const Utils::FilePath &directory,
+QList<FileNode *> scanForFiles(QPromise<Result> &promise, const Utils::FilePath &directory,
const std::function<FileNode *(const Utils::FilePath &)> factory);
namespace Internal {
template<typename Result>
QList<FileNode *> scanForFilesRecursively(
- QFutureInterface<Result> &future,
+ QPromise<Result> &promise,
double progressStart,
double progressRange,
const Utils::FilePath &directory,
@@ -46,7 +47,7 @@ QList<FileNode *> scanForFilesRecursively(
const double progressIncrement = progressRange / static_cast<double>(entries.count());
int lastIntProgress = 0;
for (const QFileInfo &entry : entries) {
- if (future.isCanceled())
+ if (promise.isCanceled())
return result;
const Utils::FilePath entryName = Utils::FilePath::fromString(entry.absoluteFilePath());
@@ -54,7 +55,7 @@ QList<FileNode *> scanForFilesRecursively(
return vc->isVcsFileOrDirectory(entryName);
})) {
if (entry.isDir())
- result.append(scanForFilesRecursively(future,
+ result.append(scanForFilesRecursively(promise,
progress,
progressIncrement,
entryName,
@@ -66,26 +67,25 @@ QList<FileNode *> scanForFilesRecursively(
}
progress += progressIncrement;
const int intProgress = std::min(static_cast<int>(progressStart + progress),
- future.progressMaximum());
+ promise.future().progressMaximum());
if (lastIntProgress < intProgress) {
- future.setProgressValue(intProgress);
+ promise.setProgressValue(intProgress);
lastIntProgress = intProgress;
}
}
- future.setProgressValue(
- std::min(static_cast<int>(progressStart + progressRange), future.progressMaximum()));
+ promise.setProgressValue(std::min(static_cast<int>(progressStart + progressRange),
+ promise.future().progressMaximum()));
return result;
}
} // namespace Internal
template<typename Result>
-QList<FileNode *> scanForFiles(QFutureInterface<Result> &future,
- const Utils::FilePath &directory,
+QList<FileNode *> scanForFiles(QPromise<Result> &promise, const Utils::FilePath &directory,
const std::function<FileNode *(const Utils::FilePath &)> factory)
{
QSet<QString> visited;
- future.setProgressRange(0, 1000000);
- return Internal::scanForFilesRecursively(future,
+ promise.setProgressRange(0, 1000000);
+ return Internal::scanForFilesRecursively(promise,
0.0,
1000000.0,
directory,
diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp
index 18b03d3ae0..5f81f473fe 100644
--- a/src/plugins/projectexplorer/projecttree.cpp
+++ b/src/plugins/projectexplorer/projecttree.cpp
@@ -6,9 +6,9 @@
#include "project.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projectnodes.h"
#include "projecttreewidget.h"
-#include "session.h"
#include "target.h"
#include <coreplugin/actionmanager/actioncontainer.h>
@@ -53,11 +53,11 @@ ProjectTree::ProjectTree(QObject *parent) : QObject(parent)
connect(qApp, &QApplication::focusChanged,
this, &ProjectTree::update);
- connect(SessionManager::instance(), &SessionManager::projectAdded,
+ connect(ProjectManager::instance(), &ProjectManager::projectAdded,
this, &ProjectTree::sessionAndTreeChanged);
- connect(SessionManager::instance(), &SessionManager::projectRemoved,
+ connect(ProjectManager::instance(), &ProjectManager::projectRemoved,
this, &ProjectTree::sessionAndTreeChanged);
- connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
+ connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged,
this, &ProjectTree::sessionChanged);
connect(this, &ProjectTree::subtreeChanged, this, &ProjectTree::treeChanged);
}
@@ -170,7 +170,7 @@ void ProjectTree::updateFromNode(Node *node)
if (node)
project = projectForNode(node);
else
- project = SessionManager::startupProject();
+ project = ProjectManager::startupProject();
setCurrent(node, project);
for (ProjectTreeWidget *widget : std::as_const(m_projectTreeWidgets))
@@ -224,7 +224,7 @@ void ProjectTree::sessionChanged()
{
if (m_currentProject) {
Core::DocumentManager::setDefaultLocationForNewFiles(m_currentProject->projectDirectory());
- } else if (Project *project = SessionManager::startupProject()) {
+ } else if (Project *project = ProjectManager::startupProject()) {
Core::DocumentManager::setDefaultLocationForNewFiles(project->projectDirectory());
updateFromNode(nullptr); // Make startup project current if there is no other current
} else {
@@ -300,7 +300,7 @@ void ProjectTree::updateFileWarning(Core::IDocument *document, const QString &te
if (!infoBar->canInfoBeAdded(infoId))
return;
const FilePath filePath = document->filePath();
- const QList<Project *> projects = SessionManager::projects();
+ const QList<Project *> projects = ProjectManager::projects();
if (projects.isEmpty())
return;
for (Project *project : projects) {
@@ -394,7 +394,7 @@ void ProjectTree::applyTreeManager(FolderNode *folder, ConstructionPhase phase)
bool ProjectTree::hasNode(const Node *node)
{
- return Utils::contains(SessionManager::projects(), [node](const Project *p) {
+ return Utils::contains(ProjectManager::projects(), [node](const Project *p) {
if (!p)
return false;
if (p->containerNode() == node)
@@ -409,7 +409,7 @@ bool ProjectTree::hasNode(const Node *node)
void ProjectTree::forEachNode(const std::function<void(Node *)> &task)
{
- const QList<Project *> projects = SessionManager::projects();
+ const QList<Project *> projects = ProjectManager::projects();
for (Project *project : projects) {
if (ProjectNode *projectNode = project->rootProjectNode()) {
task(projectNode);
@@ -430,7 +430,7 @@ Project *ProjectTree::projectForNode(const Node *node)
while (folder && folder->parentFolderNode())
folder = folder->parentFolderNode();
- return Utils::findOrDefault(SessionManager::projects(), [folder](const Project *pro) {
+ return Utils::findOrDefault(ProjectManager::projects(), [folder](const Project *pro) {
return pro->containerNode() == folder;
});
}
@@ -438,7 +438,7 @@ Project *ProjectTree::projectForNode(const Node *node)
Node *ProjectTree::nodeForFile(const FilePath &fileName)
{
Node *node = nullptr;
- for (const Project *project : SessionManager::projects()) {
+ for (const Project *project : ProjectManager::projects()) {
project->nodeForFilePath(fileName, [&](const Node *n) {
if (!node || (!node->asFileNode() && n->asFileNode()))
node = const_cast<Node *>(n);
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index 65f38626fe..a3d608ebd8 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -6,10 +6,10 @@
#include "project.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projectmodels.h"
#include "projectnodes.h"
#include "projecttree.h"
-#include "session.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
@@ -24,6 +24,7 @@
#include <utils/navigationtreeview.h>
#include <utils/progressindicator.h>
#include <utils/qtcassert.h>
+#include <utils/stylehelper.h>
#include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h>
@@ -343,7 +344,7 @@ Node *ProjectTreeWidget::nodeForFile(const FilePath &fileName)
int bestNodeExpandCount = INT_MAX;
// FIXME: Looks like this could be done with less cycles.
- for (Project *project : SessionManager::projects()) {
+ for (Project *project : ProjectManager::projects()) {
if (ProjectNode *projectNode = project->rootProjectNode()) {
projectNode->forEachGenericNode([&](Node *node) {
if (node->filePath() == fileName) {
@@ -420,7 +421,7 @@ QList<QToolButton *> ProjectTreeWidget::createToolButtons()
filter->setIcon(Icons::FILTER.icon());
filter->setToolTip(Tr::tr("Filter Tree"));
filter->setPopupMode(QToolButton::InstantPopup);
- filter->setProperty("noArrow", true);
+ filter->setProperty(StyleHelper::C_NO_ARROW, true);
auto filterMenu = new QMenu(filter);
filterMenu->addAction(m_filterProjectsAction);
diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp
index 156212a504..4eef637077 100644
--- a/src/plugins/projectexplorer/projectwelcomepage.cpp
+++ b/src/plugins/projectexplorer/projectwelcomepage.cpp
@@ -3,10 +3,9 @@
#include "projectwelcomepage.h"
-#include "session.h"
-#include "sessionmodel.h"
#include "projectexplorer.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
@@ -15,6 +14,8 @@
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/iwizardfactory.h>
+#include <coreplugin/session.h>
+#include <coreplugin/sessionmodel.h>
#include <coreplugin/welcomepagehelper.h>
#include <utils/algorithm.h>
@@ -324,7 +325,7 @@ public:
if (expanded) {
painter->setPen(textColor);
painter->setFont(sizedFont(12, option.widget));
- const FilePaths projects = SessionManager::projectsForSessionName(sessionName);
+ const FilePaths projects = ProjectManager::projectsForSessionName(sessionName);
int yy = firstBase + SESSION_LINE_HEIGHT - 3;
QFontMetrics fm(option.widget->font());
for (const FilePath &projectPath : projects) {
@@ -378,7 +379,7 @@ public:
int h = SESSION_LINE_HEIGHT;
QString sessionName = idx.data(Qt::DisplayRole).toString();
if (m_expandedSessions.contains(sessionName)) {
- const FilePaths projects = SessionManager::projectsForSessionName(sessionName);
+ const FilePaths projects = ProjectManager::projectsForSessionName(sessionName);
h += projects.size() * 40 + LINK_HEIGHT - 6;
}
return QSize(380, h + ItemGap);
@@ -579,7 +580,7 @@ public:
auto manageSessionsButton = new WelcomePageButton(this);
manageSessionsButton->setText(Tr::tr("Manage..."));
manageSessionsButton->setWithAccentColor(true);
- manageSessionsButton->setOnClicked([] { ProjectExplorerPlugin::showSessionManager(); });
+ manageSessionsButton->setOnClicked([] { SessionManager::showSessionManager(); });
auto sessionsLabel = new QLabel(this);
sessionsLabel->setFont(brandFont());
diff --git a/src/plugins/projectexplorer/projectwelcomepage.h b/src/plugins/projectexplorer/projectwelcomepage.h
index a9c8145963..7fb2a828db 100644
--- a/src/plugins/projectexplorer/projectwelcomepage.h
+++ b/src/plugins/projectexplorer/projectwelcomepage.h
@@ -12,10 +12,11 @@
#include <QAbstractListModel>
#include <QCoreApplication>
+namespace Core { class SessionModel; }
+
namespace ProjectExplorer {
namespace Internal {
-class SessionModel;
class SessionsPage;
class ProjectModel : public QAbstractListModel
@@ -56,7 +57,6 @@ public slots:
signals:
void requestProject(const Utils::FilePath &project);
- void manageSessions();
private:
void openSessionAt(int index);
@@ -64,7 +64,7 @@ private:
void createActions();
friend class SessionsPage;
- SessionModel *m_sessionModel = nullptr;
+ Core::SessionModel *m_sessionModel = nullptr;
ProjectModel *m_projectModel = nullptr;
};
diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp
index 8fae44b297..a69ee4c855 100644
--- a/src/plugins/projectexplorer/projectwindow.cpp
+++ b/src/plugins/projectexplorer/projectwindow.cpp
@@ -12,9 +12,9 @@
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
#include "projectimporter.h"
+#include "projectmanager.h"
#include "projectpanelfactory.h"
#include "projectsettingswidget.h"
-#include "session.h"
#include "target.h"
#include "targetsettingspanel.h"
@@ -352,7 +352,7 @@ public:
case Qt::FontRole: {
QFont font;
- font.setBold(m_project == SessionManager::startupProject());
+ font.setBold(m_project == ProjectManager::startupProject());
return font;
}
@@ -392,7 +392,7 @@ public:
if (role == ItemActivatedDirectlyRole) {
// Someone selected the project using the combobox or similar.
- SessionManager::setStartupProject(m_project);
+ ProjectManager::setStartupProject(m_project);
m_currentChildIndex = 0; // Use some Target page by defaults
m_targetsItem->setData(column, dat, ItemActivatedFromAboveRole); // And propagate downwards.
announceChange();
@@ -546,18 +546,18 @@ public:
m_projectSelection->showPopup();
});
- SessionManager *sessionManager = SessionManager::instance();
- connect(sessionManager, &SessionManager::projectAdded,
+ ProjectManager *sessionManager = ProjectManager::instance();
+ connect(sessionManager, &ProjectManager::projectAdded,
this, &ProjectWindowPrivate::registerProject);
- connect(sessionManager, &SessionManager::aboutToRemoveProject,
+ connect(sessionManager, &ProjectManager::aboutToRemoveProject,
this, &ProjectWindowPrivate::deregisterProject);
- connect(sessionManager, &SessionManager::startupProjectChanged,
+ connect(sessionManager, &ProjectManager::startupProjectChanged,
this, &ProjectWindowPrivate::startupProjectChanged);
m_importBuild = new QPushButton(Tr::tr("Import Existing Build..."));
connect(m_importBuild, &QPushButton::clicked,
this, &ProjectWindowPrivate::handleImportBuild);
- connect(sessionManager, &SessionManager::startupProjectChanged, this, [this](Project *project) {
+ connect(sessionManager, &ProjectManager::startupProjectChanged, this, [this](Project *project) {
m_importBuild->setEnabled(project && project->projectImporter());
});
@@ -572,9 +572,6 @@ public:
selectorView->setObjectName("ProjectSelector"); // Needed for dock widget state saving
selectorView->setWindowTitle(Tr::tr("Project Selector"));
selectorView->setAutoFillBackground(true);
- selectorView->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(selectorView, &QWidget::customContextMenuRequested,
- this, &ProjectWindowPrivate::openContextMenu);
auto activeLabel = new QLabel(Tr::tr("Active Project"));
QFont font = activeLabel->font();
@@ -677,7 +674,7 @@ public:
void projectSelected(int index)
{
Project *project = m_comboBoxModel.rootItem()->childAt(index)->m_projectItem->project();
- SessionManager::setStartupProject(project);
+ ProjectManager::setStartupProject(project);
}
ComboBoxItem *itemForProject(Project *project) const
@@ -746,8 +743,7 @@ public:
void handleManageKits()
{
if (ProjectItem *projectItem = m_projectsModel.rootItem()->childAt(0)) {
- if (auto kitPage = KitOptionsPage::instance())
- kitPage->showKit(KitManager::kit(Id::fromSetting(projectItem->data(0, KitIdRole))));
+ KitOptionsPage::showKit(KitManager::kit(Id::fromSetting(projectItem->data(0, KitIdRole))));
}
ICore::showOptionsDialog(Constants::KITS_SETTINGS_PAGE_ID);
}
@@ -780,8 +776,8 @@ public:
}
}
if (lastTarget && lastBc) {
- SessionManager::setActiveBuildConfiguration(lastTarget, lastBc, SetActive::Cascade);
- SessionManager::setActiveTarget(project, lastTarget, SetActive::Cascade);
+ lastTarget->setActiveBuildConfiguration(lastBc, SetActive::Cascade);
+ project->setActiveTarget(lastTarget, SetActive::Cascade);
}
}
diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp
index 34dc0b9aaa..83fd4d2cba 100644
--- a/src/plugins/projectexplorer/projectwizardpage.cpp
+++ b/src/plugins/projectexplorer/projectwizardpage.cpp
@@ -5,8 +5,8 @@
#include "project.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projectmodels.h"
-#include "session.h"
#include <coreplugin/icore.h>
#include <coreplugin/iversioncontrol.h>
@@ -245,12 +245,10 @@ static AddNewTree *buildAddFilesTree(FolderNode *root, const FilePaths &files,
Node *contextNode, BestNodeSelector *selector)
{
QList<AddNewTree *> children;
- const QList<FolderNode *> folderNodes = root->folderNodes();
- for (FolderNode *fn : folderNodes) {
- AddNewTree *child = buildAddFilesTree(fn, files, contextNode, selector);
- if (child)
+ root->forEachFolderNode([&](FolderNode *fn) {
+ if (AddNewTree *child = buildAddFilesTree(fn, files, contextNode, selector))
children.append(child);
- }
+ });
if (root->supportsAction(AddNewFile, root) && !root->supportsAction(InheritedFromParent, root)) {
FolderNode::AddNewInformation info = root->addNewInformation(files, contextNode);
@@ -290,7 +288,7 @@ ProjectWizardPage::ProjectWizardPage(QWidget *parent)
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(m_filesLabel);
- using namespace Utils::Layouting;
+ using namespace Layouting;
Column {
Form {
m_projectLabel, m_projectComboBox, br,
@@ -463,7 +461,7 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const FilePaths &pa
TreeItem *root = m_model.rootItem();
root->removeChildren();
- for (Project *project : SessionManager::projects()) {
+ for (Project *project : ProjectManager::projects()) {
if (ProjectNode *pn = project->rootProjectNode()) {
if (kind == IWizardFactory::ProjectWizard) {
if (AddNewTree *child = buildAddProjectTree(pn, paths.first(), context, &selector))
diff --git a/src/plugins/projectexplorer/rawprojectpart.cpp b/src/plugins/projectexplorer/rawprojectpart.cpp
index 6abbedde93..31147c3803 100644
--- a/src/plugins/projectexplorer/rawprojectpart.cpp
+++ b/src/plugins/projectexplorer/rawprojectpart.cpp
@@ -11,13 +11,14 @@
#include "target.h"
#include <ios/iosconstants.h>
+
#include <utils/algorithm.h>
namespace ProjectExplorer {
RawProjectPartFlags::RawProjectPartFlags(const ToolChain *toolChain,
const QStringList &commandLineFlags,
- const QString &includeFileBaseDir)
+ const Utils::FilePath &includeFileBaseDir)
{
// Keep the following cheap/non-blocking for the ui thread. Expensive
// operations are encapsulated in ToolChainInfo as "runners".
@@ -25,7 +26,8 @@ RawProjectPartFlags::RawProjectPartFlags(const ToolChain *toolChain,
if (toolChain) {
warningFlags = toolChain->warningFlags(commandLineFlags);
languageExtensions = toolChain->languageExtensions(commandLineFlags);
- includedFiles = toolChain->includedFiles(commandLineFlags, includeFileBaseDir);
+ includedFiles = Utils::transform(toolChain->includedFiles(commandLineFlags, includeFileBaseDir),
+ &Utils::FilePath::toFSPathString);
}
}
diff --git a/src/plugins/projectexplorer/rawprojectpart.h b/src/plugins/projectexplorer/rawprojectpart.h
index 580c83d439..ca210ed43e 100644
--- a/src/plugins/projectexplorer/rawprojectpart.h
+++ b/src/plugins/projectexplorer/rawprojectpart.h
@@ -37,7 +37,7 @@ class PROJECTEXPLORER_EXPORT RawProjectPartFlags
public:
RawProjectPartFlags() = default;
RawProjectPartFlags(const ToolChain *toolChain, const QStringList &commandLineFlags,
- const QString &includeFileBaseDir);
+ const Utils::FilePath &includeFileBaseDir);
public:
QStringList commandLineFlags;
diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp
index b5f3f8e703..29b59ad898 100644
--- a/src/plugins/projectexplorer/runconfiguration.cpp
+++ b/src/plugins/projectexplorer/runconfiguration.cpp
@@ -12,10 +12,10 @@
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projectnodes.h"
#include "runconfigurationaspects.h"
#include "runcontrol.h"
-#include "session.h"
#include "target.h"
#include <coreplugin/icontext.h>
@@ -33,7 +33,6 @@
#include <utils/utilsicons.h>
#include <utils/variablechooser.h>
-#include <QDir>
#include <QHash>
#include <QPushButton>
#include <QTimer>
@@ -217,13 +216,15 @@ bool RunConfiguration::isEnabled() const
QWidget *RunConfiguration::createConfigurationWidget()
{
- Layouting::Form builder;
- for (BaseAspect *aspect : std::as_const(m_aspects)) {
- if (aspect->isVisible())
- aspect->addToLayout(builder.finishRow());
+ Layouting::Form form;
+ for (BaseAspect *aspect : std::as_const(*this)) {
+ if (aspect->isVisible()) {
+ form.addItem(aspect);
+ form.addItem(Layouting::br);
+ }
}
-
- auto widget = builder.emerge(Layouting::WithoutMargins);
+ form.addItem(Layouting::noMargin);
+ auto widget = form.emerge();
VariableChooser::addSupportForChildWidgets(widget, &m_expander);
@@ -246,7 +247,7 @@ void RunConfiguration::addAspectFactory(const AspectFactory &aspectFactory)
QMap<Utils::Id, QVariantMap> RunConfiguration::settingsData() const
{
QMap<Utils::Id, QVariantMap> data;
- for (BaseAspect *aspect : m_aspects)
+ for (BaseAspect *aspect : *this)
aspect->toActiveMap(data[aspect->id()]);
return data;
}
@@ -254,7 +255,7 @@ QMap<Utils::Id, QVariantMap> RunConfiguration::settingsData() const
AspectContainerData RunConfiguration::aspectData() const
{
AspectContainerData data;
- for (BaseAspect *aspect : m_aspects)
+ for (BaseAspect *aspect : *this)
data.append(aspect->extractData());
return data;
}
@@ -299,6 +300,13 @@ CommandLine RunConfiguration::commandLine() const
return m_commandLineGetter();
}
+bool RunConfiguration::isPrintEnvironmentEnabled() const
+{
+ if (const auto envAspect = aspect<EnvironmentAspect>())
+ return envAspect->isPrintOnRunEnabled();
+ return false;
+}
+
void RunConfiguration::setRunnableModifier(const RunnableModifier &runnableModifier)
{
m_runnableModifier = runnableModifier;
@@ -313,7 +321,7 @@ void RunConfiguration::update()
const bool isActive = target()->isActive() && target()->activeRunConfiguration() == this;
- if (isActive && project() == SessionManager::startupProject())
+ if (isActive && project() == ProjectManager::startupProject())
ProjectExplorerPlugin::updateRunActions();
}
@@ -392,7 +400,7 @@ Runnable RunConfiguration::runnable() const
Runnable r;
r.command = commandLine();
if (auto workingDirectoryAspect = aspect<WorkingDirectoryAspect>())
- r.workingDirectory = workingDirectoryAspect->workingDirectory().onDevice(r.command.executable());
+ r.workingDirectory = r.command.executable().withNewPath(workingDirectoryAspect->workingDirectory().path());
if (auto environmentAspect = aspect<EnvironmentAspect>())
r.environment = environmentAspect->environment();
if (m_runnableModifier)
@@ -558,7 +566,7 @@ RunConfiguration *RunConfigurationFactory::create(Target *target) const
// Add the universal aspects.
for (const RunConfiguration::AspectFactory &factory : theAspectFactories)
- rc->m_aspects.registerAspect(factory(target));
+ rc->registerAspect(factory(target));
return rc;
}
diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h
index 32f61b5a30..5970414156 100644
--- a/src/plugins/projectexplorer/runconfiguration.h
+++ b/src/plugins/projectexplorer/runconfiguration.h
@@ -116,6 +116,7 @@ public:
using CommandLineGetter = std::function<Utils::CommandLine()>;
void setCommandLineGetter(const CommandLineGetter &cmdGetter);
Utils::CommandLine commandLine() const;
+ bool isPrintEnvironmentEnabled() const;
using RunnableModifier = std::function<void(Runnable &)>;
void setRunnableModifier(const RunnableModifier &extraModifier);
@@ -137,6 +138,7 @@ public:
return nullptr;
}
+ using ProjectConfiguration::registerAspect;
using AspectFactory = std::function<Utils::BaseAspect *(Target *)>;
template <class T> static void registerAspect()
{
diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp
index 9ba24c0467..ce28582d55 100644
--- a/src/plugins/projectexplorer/runconfigurationaspects.cpp
+++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp
@@ -19,8 +19,8 @@
#include <utils/fancylineedit.h>
#include <utils/layoutbuilder.h>
#include <utils/pathchooser.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <utils/utilsicons.h>
#include <QCheckBox>
@@ -33,7 +33,7 @@
#include <QPushButton>
using namespace Utils;
-using namespace Utils::Layouting;
+using namespace Layouting;
namespace ProjectExplorer {
@@ -62,12 +62,13 @@ TerminalAspect::TerminalAspect()
/*!
\reimp
*/
-void TerminalAspect::addToLayout(LayoutBuilder &builder)
+void TerminalAspect::addToLayout(LayoutItem &parent)
{
QTC_CHECK(!m_checkBox);
- m_checkBox = new QCheckBox(Tr::tr("Run in terminal"));
+ m_checkBox = createSubWidget<QCheckBox>(Tr::tr("Run in terminal"));
m_checkBox->setChecked(m_useTerminal);
- builder.addItems({{}, m_checkBox.data()});
+ m_checkBox->setEnabled(isEnabled());
+ parent.addItems({{}, m_checkBox.data()});
connect(m_checkBox.data(), &QAbstractButton::clicked, this, [this] {
m_userSet = true;
m_useTerminal = m_checkBox->isChecked();
@@ -123,7 +124,7 @@ void TerminalAspect::calculateUseTerminal()
*/
bool TerminalAspect::useTerminal() const
{
- return m_useTerminal;
+ return m_useTerminal && isEnabled();
}
/*!
@@ -163,7 +164,7 @@ WorkingDirectoryAspect::WorkingDirectoryAspect(const MacroExpander *expander,
/*!
\reimp
*/
-void WorkingDirectoryAspect::addToLayout(LayoutBuilder &builder)
+void WorkingDirectoryAspect::addToLayout(LayoutItem &builder)
{
QTC_CHECK(!m_chooser);
m_chooser = new PathChooser;
@@ -435,7 +436,7 @@ QWidget *ArgumentsAspect::setupChooser()
/*!
\reimp
*/
-void ArgumentsAspect::addToLayout(LayoutBuilder &builder)
+void ArgumentsAspect::addToLayout(LayoutItem &builder)
{
QTC_CHECK(!m_chooser && !m_multiLineChooser && !m_multiLineButton);
@@ -501,7 +502,7 @@ ExecutableAspect::ExecutableAspect(Target *target, ExecutionDeviceSelector selec
setId("ExecutableAspect");
addDataExtractor(this, &ExecutableAspect::executable, &Data::executable);
- m_executable.setPlaceHolderText(Tr::tr("<unknown>"));
+ m_executable.setPlaceHolderText(Tr::tr("path to the executable cannot be empty"));
m_executable.setLabelText(Tr::tr("Executable:"));
m_executable.setDisplayStyle(StringAspect::LabelDisplay);
@@ -570,19 +571,12 @@ void ExecutableAspect::setExpectedKind(const PathChooser::Kind expectedKind)
Sets the environment in which paths will be searched when the expected kind
of paths is chosen as PathChooser::Command or PathChooser::ExistingCommand
to \a env.
-
- \sa Utils::StringAspect::setEnvironmentChange()
*/
-void ExecutableAspect::setEnvironmentChange(const EnvironmentChange &change)
-{
- m_executable.setEnvironmentChange(change);
- if (m_alternativeExecutable)
- m_alternativeExecutable->setEnvironmentChange(change);
-}
-
void ExecutableAspect::setEnvironment(const Environment &env)
{
- setEnvironmentChange(EnvironmentChange::fromDictionary(env.toDictionary()));
+ m_executable.setEnvironment(env);
+ if (m_alternativeExecutable)
+ m_alternativeExecutable->setEnvironment(env);
}
/*!
@@ -631,7 +625,7 @@ FilePath ExecutableAspect::executable() const
: m_executable.filePath();
if (const IDevice::ConstPtr dev = executionDevice(m_target, m_selector))
- exe = exe.onDevice(dev->rootPath());
+ exe = dev->rootPath().withNewMappedPath(exe);
return exe;
}
@@ -639,11 +633,11 @@ FilePath ExecutableAspect::executable() const
/*!
\reimp
*/
-void ExecutableAspect::addToLayout(LayoutBuilder &builder)
+void ExecutableAspect::addToLayout(LayoutItem &builder)
{
- m_executable.addToLayout(builder);
+ builder.addItem(m_executable);
if (m_alternativeExecutable)
- m_alternativeExecutable->addToLayout(builder.finishRow());
+ builder.addItems({br, m_alternativeExecutable});
}
/*!
@@ -837,7 +831,7 @@ void InterpreterAspect::toMap(QVariantMap &map) const
saveToMap(map, m_currentId, QString(), settingsKey());
}
-void InterpreterAspect::addToLayout(LayoutBuilder &builder)
+void InterpreterAspect::addToLayout(LayoutItem &builder)
{
if (QTC_GUARD(m_comboBox.isNull()))
m_comboBox = new QComboBox;
diff --git a/src/plugins/projectexplorer/runconfigurationaspects.h b/src/plugins/projectexplorer/runconfigurationaspects.h
index 9e948bc6ec..9fc7364772 100644
--- a/src/plugins/projectexplorer/runconfigurationaspects.h
+++ b/src/plugins/projectexplorer/runconfigurationaspects.h
@@ -29,7 +29,7 @@ class PROJECTEXPLORER_EXPORT TerminalAspect : public Utils::BaseAspect
public:
TerminalAspect();
- void addToLayout(Utils::Layouting::LayoutBuilder &builder) override;
+ void addToLayout(Layouting::LayoutItem &parent) override;
bool useTerminal() const;
void setUseTerminalHint(bool useTerminal);
@@ -62,7 +62,7 @@ public:
explicit WorkingDirectoryAspect(const Utils::MacroExpander *expander,
EnvironmentAspect *envAspect);
- void addToLayout(Utils::Layouting::LayoutBuilder &builder) override;
+ void addToLayout(Layouting::LayoutItem &parent) override;
Utils::FilePath workingDirectory() const;
Utils::FilePath defaultWorkingDirectory() const;
@@ -91,7 +91,7 @@ class PROJECTEXPLORER_EXPORT ArgumentsAspect : public Utils::BaseAspect
public:
explicit ArgumentsAspect(const Utils::MacroExpander *macroExpander);
- void addToLayout(Utils::Layouting::LayoutBuilder &builder) override;
+ void addToLayout(Layouting::LayoutItem &parent) override;
QString arguments() const;
QString unexpandedArguments() const;
@@ -163,12 +163,11 @@ public:
void setSettingsKey(const QString &key);
void makeOverridable(const QString &overridingKey, const QString &useOverridableKey);
- void addToLayout(Utils::Layouting::LayoutBuilder &builder) override;
+ void addToLayout(Layouting::LayoutItem &parent) override;
void setLabelText(const QString &labelText);
void setPlaceHolderText(const QString &placeHolderText);
void setHistoryCompleter(const QString &historyCompleterKey);
void setExpectedKind(const Utils::PathChooser::Kind expectedKind);
- void setEnvironmentChange(const Utils::EnvironmentChange &change);
void setEnvironment(const Utils::Environment &env);
void setDisplayStyle(Utils::StringAspect::DisplayStyle style);
@@ -236,7 +235,7 @@ public:
void fromMap(const QVariantMap &) override;
void toMap(QVariantMap &) const override;
- void addToLayout(Utils::Layouting::LayoutBuilder &builder) override;
+ void addToLayout(Layouting::LayoutItem &parent) override;
struct Data : Utils::BaseAspect::Data { Interpreter interpreter; };
diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp
index 72b2e76e50..f9bafd234a 100644
--- a/src/plugins/projectexplorer/runcontrol.cpp
+++ b/src/plugins/projectexplorer/runcontrol.cpp
@@ -25,9 +25,9 @@
#include <utils/checkablemessagebox.h>
#include <utils/fileinprojectfinder.h>
#include <utils/outputformatter.h>
+#include <utils/process.h>
#include <utils/processinterface.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <utils/utilsicons.h>
#include <coreplugin/icontext.h>
@@ -255,9 +255,9 @@ public:
// A handle to the actual application process.
ProcessHandle applicationProcessHandle;
- RunControlState state = RunControlState::Initialized;
-
QList<QPointer<RunWorker>> m_workers;
+ RunControlState state = RunControlState::Initialized;
+ bool printEnvironment = false;
};
class RunControlPrivate : public QObject, public RunControlPrivateData
@@ -334,6 +334,7 @@ void RunControl::copyDataFromRunConfiguration(RunConfiguration *runConfig)
d->buildKey = runConfig->buildKey();
d->settingsData = runConfig->settingsData();
d->aspectData = runConfig->aspectData();
+ d->printEnvironment = runConfig->isPrintEnvironmentEnabled();
setTarget(runConfig->target());
@@ -817,6 +818,11 @@ Utils::Id RunControl::runMode() const
return d->runMode;
}
+bool RunControl::isPrintEnvironmentEnabled() const
+{
+ return d->printEnvironment;
+}
+
const Runnable &RunControl::runnable() const
{
return d->runnable;
@@ -1045,35 +1051,31 @@ bool RunControl::showPromptToStopDialog(const QString &title,
{
// Show a question message box where user can uncheck this
// question for this class.
- Utils::CheckableMessageBox messageBox(Core::ICore::dialogParent());
- messageBox.setWindowTitle(title);
- messageBox.setText(text);
- messageBox.setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::Cancel);
+ QMap<QMessageBox::StandardButton, QString> buttonTexts;
if (!stopButtonText.isEmpty())
- messageBox.button(QDialogButtonBox::Yes)->setText(stopButtonText);
+ buttonTexts[QMessageBox::Yes] = stopButtonText;
if (!cancelButtonText.isEmpty())
- messageBox.button(QDialogButtonBox::Cancel)->setText(cancelButtonText);
- messageBox.setDefaultButton(QDialogButtonBox::Yes);
- if (prompt) {
- messageBox.setCheckBoxText(Utils::CheckableMessageBox::msgDoNotAskAgain());
- messageBox.setChecked(false);
- } else {
- messageBox.setCheckBoxVisible(false);
- }
- messageBox.exec();
- const bool close = messageBox.clickedStandardButton() == QDialogButtonBox::Yes;
- if (close && prompt && messageBox.isChecked())
- *prompt = false;
- return close;
+ buttonTexts[QMessageBox::Cancel] = cancelButtonText;
+
+ CheckableDecider decider;
+ if (prompt)
+ decider = CheckableDecider(prompt);
+
+ auto selected = CheckableMessageBox::question(Core::ICore::dialogParent(),
+ title,
+ text,
+ decider,
+ QMessageBox::Yes | QMessageBox::Cancel,
+ QMessageBox::Yes);
+
+ return selected == QMessageBox::Yes;
}
void RunControl::provideAskPassEntry(Environment &env)
{
- if (env.value("SUDO_ASKPASS").isEmpty()) {
- const FilePath askpass = SshSettings::askpassFilePath();
- if (askpass.exists())
- env.set("SUDO_ASKPASS", askpass.toUserOutput());
- }
+ const FilePath askpass = SshSettings::askpassFilePath();
+ if (askpass.exists())
+ env.setFallback("SUDO_ASKPASS", askpass.toUserOutput());
}
bool RunControlPrivate::isAllowedTransition(RunControlState from, RunControlState to)
@@ -1175,7 +1177,7 @@ public:
bool m_runAsRoot = false;
- QtcProcess m_process;
+ Process m_process;
QTextCodec *m_outputCodec = nullptr;
QTextCodec::ConverterState m_outputCodecState;
@@ -1212,11 +1214,11 @@ SimpleTargetRunnerPrivate::SimpleTargetRunnerPrivate(SimpleTargetRunner *parent)
: q(parent)
{
m_process.setProcessChannelMode(defaultProcessChannelMode());
- connect(&m_process, &QtcProcess::started, this, &SimpleTargetRunnerPrivate::forwardStarted);
- connect(&m_process, &QtcProcess::done, this, &SimpleTargetRunnerPrivate::handleDone);
- connect(&m_process, &QtcProcess::readyReadStandardError,
+ connect(&m_process, &Process::started, this, &SimpleTargetRunnerPrivate::forwardStarted);
+ connect(&m_process, &Process::done, this, &SimpleTargetRunnerPrivate::handleDone);
+ connect(&m_process, &Process::readyReadStandardError,
this, &SimpleTargetRunnerPrivate::handleStandardError);
- connect(&m_process, &QtcProcess::readyReadStandardOutput,
+ connect(&m_process, &Process::readyReadStandardOutput,
this, &SimpleTargetRunnerPrivate::handleStandardOutput);
if (WinDebugInterface::instance()) {
@@ -1371,7 +1373,7 @@ void SimpleTargetRunnerPrivate::start()
Encapsulates processes running in a console or as GUI processes,
captures debug output of GUI processes on Windows (outputDebugString()).
- \sa Utils::QtcProcess
+ \sa Utils::Process
*/
SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
@@ -1433,11 +1435,20 @@ void SimpleTargetRunner::start()
d->m_stopForced = false;
d->m_stopReported = false;
d->disconnect(this);
- d->m_process.setTerminalMode(useTerminal ? Utils::TerminalMode::On : Utils::TerminalMode::Off);
+ d->m_process.setTerminalMode(useTerminal ? Utils::TerminalMode::Run : Utils::TerminalMode::Off);
d->m_runAsRoot = runAsRoot;
const QString msg = Tr::tr("Starting %1...").arg(d->m_command.displayName());
appendMessage(msg, NormalMessageFormat);
+ if (runControl()->isPrintEnvironmentEnabled()) {
+ appendMessage(Tr::tr("Environment:"), NormalMessageFormat);
+ runControl()->runnable().environment
+ .forEachEntry([this](const QString &key, const QString &value, bool enabled) {
+ if (enabled)
+ appendMessage(key + '=' + value, StdOutFormat);
+ });
+ appendMessage({}, StdOutFormat);
+ }
const bool isDesktop = !d->m_command.executable().needsDevice();
if (isDesktop && d->m_command.isEmpty()) {
@@ -1653,9 +1664,9 @@ void RunWorker::reportFailure(const QString &msg)
* Appends a message in the specified \a format to
* the owning RunControl's \uicontrol{Application Output} pane.
*/
-void RunWorker::appendMessage(const QString &msg, OutputFormat format)
+void RunWorker::appendMessage(const QString &msg, OutputFormat format, bool appendNewLine)
{
- if (msg.endsWith('\n'))
+ if (!appendNewLine || msg.endsWith('\n'))
emit d->runControl->appendMessage(msg, format);
else
emit d->runControl->appendMessage(msg + '\n', format);
diff --git a/src/plugins/projectexplorer/runcontrol.h b/src/plugins/projectexplorer/runcontrol.h
index d779b693a8..84a5b5c166 100644
--- a/src/plugins/projectexplorer/runcontrol.h
+++ b/src/plugins/projectexplorer/runcontrol.h
@@ -67,7 +67,7 @@ public:
QVariant recordedData(const QString &channel) const;
// Part of read-only interface of RunControl for convenience.
- void appendMessage(const QString &msg, Utils::OutputFormat format);
+ void appendMessage(const QString &msg, Utils::OutputFormat format, bool appendNewLine = true);
void appendMessageChunk(const QString &msg, Utils::OutputFormat format);
IDeviceConstPtr device() const;
@@ -205,6 +205,7 @@ public:
void setupFormatter(Utils::OutputFormatter *formatter) const;
Utils::Id runMode() const;
+ bool isPrintEnvironmentEnabled() const;
const Runnable &runnable() const;
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
index bd8b30f2b7..43edee9b66 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
@@ -10,9 +10,10 @@
#include "projectconfigurationmodel.h"
#include "projectexplorertr.h"
#include "runconfiguration.h"
-#include "session.h"
#include "target.h"
+#include <coreplugin/session.h>
+
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
@@ -291,11 +292,10 @@ void RunSettingsWidget::currentDeployConfigurationChanged(int index)
if (m_ignoreChanges.isLocked())
return;
if (index == -1)
- SessionManager::setActiveDeployConfiguration(m_target, nullptr, SetActive::Cascade);
+ m_target->setActiveDeployConfiguration(nullptr, SetActive::Cascade);
else
- SessionManager::setActiveDeployConfiguration(m_target,
- qobject_cast<DeployConfiguration *>(m_target->deployConfigurationModel()->projectConfigurationAt(index)),
- SetActive::Cascade);
+ m_target->setActiveDeployConfiguration(qobject_cast<DeployConfiguration *>(m_target->deployConfigurationModel()->projectConfigurationAt(index)),
+ SetActive::Cascade);
}
void RunSettingsWidget::aboutToShowDeployMenu()
@@ -309,7 +309,7 @@ void RunSettingsWidget::aboutToShowDeployMenu()
if (!newDc)
return;
m_target->addDeployConfiguration(newDc);
- SessionManager::setActiveDeployConfiguration(m_target, newDc, SetActive::Cascade);
+ m_target->setActiveDeployConfiguration(newDc, SetActive::Cascade);
m_removeDeployToolButton->setEnabled(m_target->deployConfigurations().size() > 1);
});
}
diff --git a/src/plugins/projectexplorer/selectablefilesmodel.cpp b/src/plugins/projectexplorer/selectablefilesmodel.cpp
index 365c319992..de5b0b79b4 100644
--- a/src/plugins/projectexplorer/selectablefilesmodel.cpp
+++ b/src/plugins/projectexplorer/selectablefilesmodel.cpp
@@ -9,10 +9,10 @@
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
+#include <utils/async.h>
#include <utils/fancylineedit.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/pathchooser.h>
-#include <utils/runextensions.h>
#include <utils/stringutils.h>
#include <QDialogButtonBox>
@@ -51,13 +51,13 @@ void SelectableFilesFromDirModel::startParsing(const Utils::FilePath &baseDir)
m_rootForFuture->fullPath = baseDir;
m_rootForFuture->isDir = true;
- m_watcher.setFuture(Utils::runAsync(&SelectableFilesFromDirModel::run, this));
+ m_watcher.setFuture(Utils::asyncRun(&SelectableFilesFromDirModel::run, this));
}
-void SelectableFilesFromDirModel::run(QFutureInterface<void> &fi)
+void SelectableFilesFromDirModel::run(QPromise<void> &promise)
{
m_futureCount = 0;
- buildTree(m_baseDir, m_rootForFuture, fi, 5);
+ buildTree(m_baseDir, m_rootForFuture, promise, 5);
}
void SelectableFilesFromDirModel::buildTreeFinished()
@@ -97,7 +97,7 @@ SelectableFilesModel::FilterState SelectableFilesModel::filter(Tree *t)
}
void SelectableFilesFromDirModel::buildTree(const Utils::FilePath &baseDir, Tree *tree,
- QFutureInterface<void> &fi, int symlinkDepth)
+ QPromise<void> &promise, int symlinkDepth)
{
if (symlinkDepth == 0)
return;
@@ -111,7 +111,7 @@ void SelectableFilesFromDirModel::buildTree(const Utils::FilePath &baseDir, Tree
Utils::FilePath fn = Utils::FilePath::fromFileInfo(fileInfo);
if (m_futureCount % 100) {
emit parsingProgress(fn);
- if (fi.isCanceled())
+ if (promise.isCanceled())
return;
}
++m_futureCount;
@@ -121,7 +121,7 @@ void SelectableFilesFromDirModel::buildTree(const Utils::FilePath &baseDir, Tree
t->name = fileInfo.fileName();
t->fullPath = fn;
t->isDir = true;
- buildTree(fn, t, fi, symlinkDepth - fileInfo.isSymLink());
+ buildTree(fn, t, promise, symlinkDepth - fileInfo.isSymLink());
allChecked &= t->checked == Qt::Checked;
allUnchecked &= t->checked == Qt::Unchecked;
tree->childDirectories.append(t);
diff --git a/src/plugins/projectexplorer/selectablefilesmodel.h b/src/plugins/projectexplorer/selectablefilesmodel.h
index 6340e2d1a2..8c47fbd990 100644
--- a/src/plugins/projectexplorer/selectablefilesmodel.h
+++ b/src/plugins/projectexplorer/selectablefilesmodel.h
@@ -9,7 +9,6 @@
#include <QAbstractItemModel>
#include <QDialog>
-#include <QFutureInterface>
#include <QFutureWatcher>
#include <QLabel>
#include <QRegularExpression>
@@ -147,11 +146,9 @@ signals:
void parsingProgress(const Utils::FilePath &fileName);
private:
- void buildTree(const Utils::FilePath &baseDir,
- Tree *tree,
- QFutureInterface<void> &fi,
+ void buildTree(const Utils::FilePath &baseDir, Tree *tree, QPromise<void> &promise,
int symlinkDepth);
- void run(QFutureInterface<void> &fi);
+ void run(QPromise<void> &promise);
void buildTreeFinished();
// Used in the future thread need to all not used after calling startParsing
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
deleted file mode 100644
index 6dcfd9a461..0000000000
--- a/src/plugins/projectexplorer/session.cpp
+++ /dev/null
@@ -1,1262 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "session.h"
-
-#include "buildconfiguration.h"
-#include "deployconfiguration.h"
-#include "editorconfiguration.h"
-#include "kit.h"
-#include "project.h"
-#include "projectexplorer.h"
-#include "projectexplorerconstants.h"
-#include "projectexplorertr.h"
-#include "projectnodes.h"
-#include "target.h"
-
-#include <coreplugin/coreconstants.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/foldernavigationwidget.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/idocument.h>
-#include <coreplugin/imode.h>
-#include <coreplugin/modemanager.h>
-#include <coreplugin/progressmanager/progressmanager.h>
-
-#include <texteditor/texteditor.h>
-
-#include <utils/algorithm.h>
-#include <utils/filepath.h>
-#include <utils/qtcassert.h>
-#include <utils/stylehelper.h>
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-#include <QMessageBox>
-#include <QPushButton>
-
-#ifdef WITH_TESTS
-#include <QTemporaryFile>
-#include <QTest>
-#include <vector>
-#endif
-
-using namespace Core;
-using namespace Utils;
-using namespace ProjectExplorer::Internal;
-
-namespace ProjectExplorer {
-
-const char DEFAULT_SESSION[] = "default";
-const char LAST_ACTIVE_TIMES_KEY[] = "LastActiveTimes";
-
-/*!
- \class ProjectExplorer::SessionManager
-
- \brief The SessionManager class manages sessions.
-
- TODO the interface of this class is not really great.
- The implementation suffers from that all the functions from the
- public interface just wrap around functions which do the actual work.
- This could be improved.
-*/
-
-class SessionManagerPrivate
-{
-public:
- void restoreValues(const PersistentSettingsReader &reader);
- void restoreDependencies(const PersistentSettingsReader &reader);
- void restoreStartupProject(const PersistentSettingsReader &reader);
- void restoreEditors(const PersistentSettingsReader &reader);
- void restoreProjects(const FilePaths &fileList);
- void askUserAboutFailedProjects();
- void sessionLoadingProgress();
-
- bool recursiveDependencyCheck(const FilePath &newDep, const FilePath &checkDep) const;
- FilePaths dependencies(const FilePath &proName) const;
- FilePaths dependenciesOrder() const;
- void dependencies(const FilePath &proName, FilePaths &result) const;
-
- static QString windowTitleAddition(const FilePath &filePath);
- static QString sessionTitle(const FilePath &filePath);
-
- bool hasProjects() const { return !m_projects.isEmpty(); }
-
- QString m_sessionName = QLatin1String(DEFAULT_SESSION);
- bool m_virginSession = true;
- bool m_loadingSession = false;
- bool m_casadeSetActive = false;
-
- mutable QStringList m_sessions;
- mutable QHash<QString, QDateTime> m_sessionDateTimes;
- QHash<QString, QDateTime> m_lastActiveTimes;
-
- Project *m_startupProject = nullptr;
- QList<Project *> m_projects;
- FilePaths m_failedProjects;
- QMap<FilePath, FilePaths> m_depMap;
- QMap<QString, QVariant> m_values;
- QFutureInterface<void> m_future;
- PersistentSettingsWriter *m_writer = nullptr;
-
-private:
- static QString locationInProject(const FilePath &filePath);
-};
-
-static SessionManager *m_instance = nullptr;
-static SessionManagerPrivate *d = nullptr;
-
-static QString projectFolderId(Project *pro)
-{
- return pro->projectFilePath().toString();
-}
-
-const int PROJECT_SORT_VALUE = 100;
-
-SessionManager::SessionManager(QObject *parent) : QObject(parent)
-{
- m_instance = this;
- d = new SessionManagerPrivate;
-
- connect(ModeManager::instance(), &ModeManager::currentModeChanged,
- this, &SessionManager::saveActiveMode);
-
- connect(ICore::instance(), &ICore::saveSettingsRequested, this, [] {
- QVariantMap times;
- for (auto it = d->m_lastActiveTimes.cbegin(); it != d->m_lastActiveTimes.cend(); ++it)
- times.insert(it.key(), it.value());
- ICore::settings()->setValue(LAST_ACTIVE_TIMES_KEY, times);
- });
-
- connect(EditorManager::instance(), &EditorManager::editorCreated,
- this, &SessionManager::configureEditor);
- connect(this, &SessionManager::projectAdded,
- EditorManager::instance(), &EditorManager::updateWindowTitles);
- connect(this, &SessionManager::projectRemoved,
- EditorManager::instance(), &EditorManager::updateWindowTitles);
- connect(this, &SessionManager::projectDisplayNameChanged,
- EditorManager::instance(), &EditorManager::updateWindowTitles);
- connect(EditorManager::instance(), &EditorManager::editorOpened,
- this, &SessionManager::markSessionFileDirty);
- connect(EditorManager::instance(), &EditorManager::editorsClosed,
- this, &SessionManager::markSessionFileDirty);
-
- EditorManager::setWindowTitleAdditionHandler(&SessionManagerPrivate::windowTitleAddition);
- EditorManager::setSessionTitleHandler(&SessionManagerPrivate::sessionTitle);
-}
-
-SessionManager::~SessionManager()
-{
- EditorManager::setWindowTitleAdditionHandler({});
- EditorManager::setSessionTitleHandler({});
- emit m_instance->aboutToUnloadSession(d->m_sessionName);
- delete d->m_writer;
- delete d;
- d = nullptr;
-}
-
-SessionManager *SessionManager::instance()
-{
- return m_instance;
-}
-
-bool SessionManager::isDefaultVirgin()
-{
- return isDefaultSession(d->m_sessionName) && d->m_virginSession;
-}
-
-bool SessionManager::isDefaultSession(const QString &session)
-{
- return session == QLatin1String(DEFAULT_SESSION);
-}
-
-void SessionManager::saveActiveMode(Id mode)
-{
- if (mode != Core::Constants::MODE_WELCOME)
- setValue(QLatin1String("ActiveMode"), mode.toString());
-}
-
-bool SessionManagerPrivate::recursiveDependencyCheck(const FilePath &newDep,
- const FilePath &checkDep) const
-{
- if (newDep == checkDep)
- return false;
-
- const FilePaths depList = m_depMap.value(checkDep);
- for (const FilePath &dependency : depList) {
- if (!recursiveDependencyCheck(newDep, dependency))
- return false;
- }
-
- return true;
-}
-
-/*
- * The dependency management exposes an interface based on projects, but
- * is internally purely string based. This is suboptimal. Probably it would be
- * nicer to map the filenames to projects on load and only map it back to
- * filenames when saving.
- */
-
-QList<Project *> SessionManager::dependencies(const Project *project)
-{
- const FilePath proName = project->projectFilePath();
- const FilePaths proDeps = d->m_depMap.value(proName);
-
- QList<Project *> projects;
- for (const FilePath &dep : proDeps) {
- Project *pro = Utils::findOrDefault(d->m_projects, [&dep](Project *p) {
- return p->projectFilePath() == dep;
- });
- if (pro)
- projects += pro;
- }
-
- return projects;
-}
-
-bool SessionManager::hasDependency(const Project *project, const Project *depProject)
-{
- const FilePath proName = project->projectFilePath();
- const FilePath depName = depProject->projectFilePath();
-
- const FilePaths proDeps = d->m_depMap.value(proName);
- return proDeps.contains(depName);
-}
-
-bool SessionManager::canAddDependency(const Project *project, const Project *depProject)
-{
- const FilePath newDep = project->projectFilePath();
- const FilePath checkDep = depProject->projectFilePath();
-
- return d->recursiveDependencyCheck(newDep, checkDep);
-}
-
-bool SessionManager::addDependency(Project *project, Project *depProject)
-{
- const FilePath proName = project->projectFilePath();
- const FilePath depName = depProject->projectFilePath();
-
- // check if this dependency is valid
- if (!d->recursiveDependencyCheck(proName, depName))
- return false;
-
- FilePaths proDeps = d->m_depMap.value(proName);
- if (!proDeps.contains(depName)) {
- proDeps.append(depName);
- d->m_depMap[proName] = proDeps;
- }
- emit m_instance->dependencyChanged(project, depProject);
-
- return true;
-}
-
-void SessionManager::removeDependency(Project *project, Project *depProject)
-{
- const FilePath proName = project->projectFilePath();
- const FilePath depName = depProject->projectFilePath();
-
- FilePaths proDeps = d->m_depMap.value(proName);
- proDeps.removeAll(depName);
- if (proDeps.isEmpty())
- d->m_depMap.remove(proName);
- else
- d->m_depMap[proName] = proDeps;
- emit m_instance->dependencyChanged(project, depProject);
-}
-
-bool SessionManager::isProjectConfigurationCascading()
-{
- return d->m_casadeSetActive;
-}
-
-void SessionManager::setProjectConfigurationCascading(bool b)
-{
- d->m_casadeSetActive = b;
- markSessionFileDirty();
-}
-
-void SessionManager::setActiveTarget(Project *project, Target *target, SetActive cascade)
-{
- QTC_ASSERT(project, return);
-
- if (project->isShuttingDown())
- return;
-
- project->setActiveTarget(target);
-
- if (!target) // never cascade setting no target
- return;
-
- if (cascade != SetActive::Cascade || !d->m_casadeSetActive)
- return;
-
- Utils::Id kitId = target->kit()->id();
- for (Project *otherProject : SessionManager::projects()) {
- if (otherProject == project)
- continue;
- if (Target *otherTarget = Utils::findOrDefault(otherProject->targets(),
- [kitId](Target *t) { return t->kit()->id() == kitId; }))
- otherProject->setActiveTarget(otherTarget);
- }
-}
-
-void SessionManager::setActiveBuildConfiguration(Target *target, BuildConfiguration *bc, SetActive cascade)
-{
- QTC_ASSERT(target, return);
- QTC_ASSERT(target->project(), return);
-
- if (target->project()->isShuttingDown() || target->isShuttingDown())
- return;
-
- target->setActiveBuildConfiguration(bc);
-
- if (!bc)
- return;
- if (cascade != SetActive::Cascade || !d->m_casadeSetActive)
- return;
-
- Utils::Id kitId = target->kit()->id();
- QString name = bc->displayName(); // We match on displayname
- for (Project *otherProject : SessionManager::projects()) {
- if (otherProject == target->project())
- continue;
- Target *otherTarget = otherProject->activeTarget();
- if (!otherTarget || otherTarget->kit()->id() != kitId)
- continue;
-
- for (BuildConfiguration *otherBc : otherTarget->buildConfigurations()) {
- if (otherBc->displayName() == name) {
- otherTarget->setActiveBuildConfiguration(otherBc);
- break;
- }
- }
- }
-}
-
-void SessionManager::setActiveDeployConfiguration(Target *target, DeployConfiguration *dc, SetActive cascade)
-{
- QTC_ASSERT(target, return);
- QTC_ASSERT(target->project(), return);
-
- if (target->project()->isShuttingDown() || target->isShuttingDown())
- return;
-
- target->setActiveDeployConfiguration(dc);
-
- if (!dc)
- return;
- if (cascade != SetActive::Cascade || !d->m_casadeSetActive)
- return;
-
- Utils::Id kitId = target->kit()->id();
- QString name = dc->displayName(); // We match on displayname
- for (Project *otherProject : SessionManager::projects()) {
- if (otherProject == target->project())
- continue;
- Target *otherTarget = otherProject->activeTarget();
- if (!otherTarget || otherTarget->kit()->id() != kitId)
- continue;
-
- for (DeployConfiguration *otherDc : otherTarget->deployConfigurations()) {
- if (otherDc->displayName() == name) {
- otherTarget->setActiveDeployConfiguration(otherDc);
- break;
- }
- }
- }
-}
-
-void SessionManager::setStartupProject(Project *startupProject)
-{
- QTC_ASSERT((!startupProject && d->m_projects.isEmpty())
- || (startupProject && d->m_projects.contains(startupProject)), return);
-
- if (d->m_startupProject == startupProject)
- return;
-
- d->m_startupProject = startupProject;
- if (d->m_startupProject && d->m_startupProject->needsConfiguration()) {
- ModeManager::activateMode(Constants::MODE_SESSION);
- ModeManager::setFocusToCurrentMode();
- }
- FolderNavigationWidgetFactory::setFallbackSyncFilePath(
- startupProject ? startupProject->projectFilePath().parentDir() : FilePath());
- emit m_instance->startupProjectChanged(startupProject);
-}
-
-Project *SessionManager::startupProject()
-{
- return d->m_startupProject;
-}
-
-Target *SessionManager::startupTarget()
-{
- return d->m_startupProject ? d->m_startupProject->activeTarget() : nullptr;
-}
-
-BuildSystem *SessionManager::startupBuildSystem()
-{
- Target *t = startupTarget();
- return t ? t->buildSystem() : nullptr;
-}
-
-/*!
- * Returns the RunConfiguration of the currently active target
- * of the startup project, if such exists, or \c nullptr otherwise.
- */
-
-
-RunConfiguration *SessionManager::startupRunConfiguration()
-{
- Target *t = startupTarget();
- return t ? t->activeRunConfiguration() : nullptr;
-}
-
-void SessionManager::addProject(Project *pro)
-{
- QTC_ASSERT(pro, return);
- QTC_CHECK(!pro->displayName().isEmpty());
- QTC_CHECK(pro->id().isValid());
-
- d->m_virginSession = false;
- QTC_ASSERT(!d->m_projects.contains(pro), return);
-
- d->m_projects.append(pro);
-
- connect(pro, &Project::displayNameChanged,
- m_instance, [pro]() { emit m_instance->projectDisplayNameChanged(pro); });
-
- emit m_instance->projectAdded(pro);
- const auto updateFolderNavigation = [pro] {
- // destructing projects might trigger changes, so check if the project is actually there
- if (QTC_GUARD(d->m_projects.contains(pro))) {
- const QIcon icon = pro->rootProjectNode() ? pro->rootProjectNode()->icon() : QIcon();
- FolderNavigationWidgetFactory::insertRootDirectory({projectFolderId(pro),
- PROJECT_SORT_VALUE,
- pro->displayName(),
- pro->projectFilePath().parentDir(),
- icon});
- }
- };
- updateFolderNavigation();
- configureEditors(pro);
- connect(pro, &Project::fileListChanged, m_instance, [pro, updateFolderNavigation]() {
- configureEditors(pro);
- updateFolderNavigation(); // update icon
- });
- connect(pro, &Project::displayNameChanged, m_instance, updateFolderNavigation);
-
- if (!startupProject())
- setStartupProject(pro);
-}
-
-void SessionManager::removeProject(Project *project)
-{
- d->m_virginSession = false;
- QTC_ASSERT(project, return);
- removeProjects({project});
-}
-
-bool SessionManager::loadingSession()
-{
- return d->m_loadingSession;
-}
-
-bool SessionManager::save()
-{
- emit m_instance->aboutToSaveSession();
-
- const FilePath filePath = sessionNameToFileName(d->m_sessionName);
- QVariantMap data;
-
- // See the explanation at loadSession() for how we handle the implicit default session.
- if (isDefaultVirgin()) {
- if (filePath.exists()) {
- PersistentSettingsReader reader;
- if (!reader.load(filePath)) {
- QMessageBox::warning(ICore::dialogParent(), Tr::tr("Error while saving session"),
- Tr::tr("Could not save session %1").arg(filePath.toUserOutput()));
- return false;
- }
- data = reader.restoreValues();
- }
- } else {
- // save the startup project
- if (d->m_startupProject)
- data.insert("StartupProject", d->m_startupProject->projectFilePath().toSettings());
-
- const QColor c = StyleHelper::requestedBaseColor();
- if (c.isValid()) {
- QString tmp = QString::fromLatin1("#%1%2%3")
- .arg(c.red(), 2, 16, QLatin1Char('0'))
- .arg(c.green(), 2, 16, QLatin1Char('0'))
- .arg(c.blue(), 2, 16, QLatin1Char('0'));
- data.insert(QLatin1String("Color"), tmp);
- }
-
- FilePaths projectFiles = Utils::transform(projects(), &Project::projectFilePath);
- // Restore information on projects that failed to load:
- // don't read projects to the list, which the user loaded
- for (const FilePath &failed : std::as_const(d->m_failedProjects)) {
- if (!projectFiles.contains(failed))
- projectFiles << failed;
- }
-
- data.insert("ProjectList", Utils::transform<QStringList>(projectFiles,
- &FilePath::toString));
- data.insert("CascadeSetActive", d->m_casadeSetActive);
-
- QVariantMap depMap;
- auto i = d->m_depMap.constBegin();
- while (i != d->m_depMap.constEnd()) {
- QString key = i.key().toString();
- QStringList values;
- const FilePaths valueList = i.value();
- for (const FilePath &value : valueList)
- values << value.toString();
- depMap.insert(key, values);
- ++i;
- }
- data.insert(QLatin1String("ProjectDependencies"), QVariant(depMap));
- data.insert(QLatin1String("EditorSettings"), EditorManager::saveState().toBase64());
- }
-
- const auto end = d->m_values.constEnd();
- QStringList keys;
- for (auto it = d->m_values.constBegin(); it != end; ++it) {
- data.insert(QLatin1String("value-") + it.key(), it.value());
- keys << it.key();
- }
- data.insert(QLatin1String("valueKeys"), keys);
-
- if (!d->m_writer || d->m_writer->fileName() != filePath) {
- delete d->m_writer;
- d->m_writer = new PersistentSettingsWriter(filePath, "QtCreatorSession");
- }
- const bool result = d->m_writer->save(data, ICore::dialogParent());
- if (result) {
- if (!isDefaultVirgin())
- d->m_sessionDateTimes.insert(activeSession(), QDateTime::currentDateTime());
- } else {
- QMessageBox::warning(ICore::dialogParent(), Tr::tr("Error while saving session"),
- Tr::tr("Could not save session to file %1").arg(d->m_writer->fileName().toUserOutput()));
- }
-
- return result;
-}
-
-/*!
- Closes all projects
- */
-void SessionManager::closeAllProjects()
-{
- removeProjects(projects());
-}
-
-const QList<Project *> SessionManager::projects()
-{
- return d->m_projects;
-}
-
-bool SessionManager::hasProjects()
-{
- return d->hasProjects();
-}
-
-bool SessionManager::hasProject(Project *p)
-{
- return d->m_projects.contains(p);
-}
-
-FilePaths SessionManagerPrivate::dependencies(const FilePath &proName) const
-{
- FilePaths result;
- dependencies(proName, result);
- return result;
-}
-
-void SessionManagerPrivate::dependencies(const FilePath &proName, FilePaths &result) const
-{
- const FilePaths depends = m_depMap.value(proName);
-
- for (const FilePath &dep : depends)
- dependencies(dep, result);
-
- if (!result.contains(proName))
- result.append(proName);
-}
-
-QString SessionManagerPrivate::sessionTitle(const FilePath &filePath)
-{
- if (SessionManager::isDefaultSession(d->m_sessionName)) {
- if (filePath.isEmpty()) {
- // use single project's name if there is only one loaded.
- const QList<Project *> projects = SessionManager::projects();
- if (projects.size() == 1)
- return projects.first()->displayName();
- }
- } else {
- QString sessionName = d->m_sessionName;
- if (sessionName.isEmpty())
- sessionName = Tr::tr("Untitled");
- return sessionName;
- }
- return QString();
-}
-
-QString SessionManagerPrivate::locationInProject(const FilePath &filePath) {
- const Project *project = SessionManager::projectForFile(filePath);
- if (!project)
- return QString();
-
- const FilePath parentDir = filePath.parentDir();
- if (parentDir == project->projectDirectory())
- return "@ " + project->displayName();
-
- if (filePath.isChildOf(project->projectDirectory())) {
- const FilePath dirInProject = parentDir.relativeChildPath(project->projectDirectory());
- return "(" + dirInProject.toUserOutput() + " @ " + project->displayName() + ")";
- }
-
- // For a file that is "outside" the project it belongs to, we display its
- // dir's full path because it is easier to read than a series of "../../.".
- // Example: /home/hugo/GenericProject/App.files lists /home/hugo/lib/Bar.cpp
- return "(" + parentDir.toUserOutput() + " @ " + project->displayName() + ")";
-}
-
-QString SessionManagerPrivate::windowTitleAddition(const FilePath &filePath)
-{
- return filePath.isEmpty() ? QString() : locationInProject(filePath);
-}
-
-FilePaths SessionManagerPrivate::dependenciesOrder() const
-{
- QList<QPair<FilePath, FilePaths>> unordered;
- FilePaths ordered;
-
- // copy the map to a temporary list
- for (const Project *pro : m_projects) {
- const FilePath proName = pro->projectFilePath();
- const FilePaths depList = filtered(m_depMap.value(proName),
- [this](const FilePath &proPath) {
- return contains(m_projects, [proPath](const Project *p) {
- return p->projectFilePath() == proPath;
- });
- });
- unordered.push_back({proName, depList});
- }
-
- while (!unordered.isEmpty()) {
- for (int i = (unordered.count() - 1); i >= 0; --i) {
- if (unordered.at(i).second.isEmpty()) {
- ordered << unordered.at(i).first;
- unordered.removeAt(i);
- }
- }
-
- // remove the handled projects from the dependency lists
- // of the remaining unordered projects
- for (int i = 0; i < unordered.count(); ++i) {
- for (const FilePath &pro : std::as_const(ordered)) {
- FilePaths depList = unordered.at(i).second;
- depList.removeAll(pro);
- unordered[i].second = depList;
- }
- }
- }
-
- return ordered;
-}
-
-QList<Project *> SessionManager::projectOrder(const Project *project)
-{
- QList<Project *> result;
-
- FilePaths pros;
- if (project)
- pros = d->dependencies(project->projectFilePath());
- else
- pros = d->dependenciesOrder();
-
- for (const FilePath &proFile : std::as_const(pros)) {
- for (Project *pro : projects()) {
- if (pro->projectFilePath() == proFile) {
- result << pro;
- break;
- }
- }
- }
-
- return result;
-}
-
-Project *SessionManager::projectForFile(const FilePath &fileName)
-{
- if (Project * const project = Utils::findOrDefault(SessionManager::projects(),
- [&fileName](const Project *p) { return p->isKnownFile(fileName); })) {
- return project;
- }
- return Utils::findOrDefault(SessionManager::projects(),
- [&fileName](const Project *p) {
- for (const Target * const target : p->targets()) {
- for (const BuildConfiguration * const bc : target->buildConfigurations()) {
- if (fileName.isChildOf(bc->buildDirectory()))
- return false;
- }
- }
- return fileName.isChildOf(p->projectDirectory());
- });
-}
-
-Project *SessionManager::projectWithProjectFilePath(const FilePath &filePath)
-{
- return Utils::findOrDefault(SessionManager::projects(),
- [&filePath](const Project *p) { return p->projectFilePath() == filePath; });
-}
-
-void SessionManager::configureEditor(IEditor *editor, const QString &fileName)
-{
- if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) {
- Project *project = projectForFile(Utils::FilePath::fromString(fileName));
- // Global settings are the default.
- if (project)
- project->editorConfiguration()->configureEditor(textEditor);
- }
-}
-
-void SessionManager::configureEditors(Project *project)
-{
- const QList<IDocument *> documents = DocumentModel::openedDocuments();
- for (IDocument *document : documents) {
- if (project->isKnownFile(document->filePath())) {
- const QList<IEditor *> editors = DocumentModel::editorsForDocument(document);
- for (IEditor *editor : editors) {
- if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) {
- project->editorConfiguration()->configureEditor(textEditor);
- }
- }
- }
- }
-}
-
-void SessionManager::removeProjects(const QList<Project *> &remove)
-{
- for (Project *pro : remove)
- emit m_instance->aboutToRemoveProject(pro);
-
- bool changeStartupProject = false;
-
- // Delete projects
- for (Project *pro : remove) {
- pro->saveSettings();
- pro->markAsShuttingDown();
-
- // Remove the project node:
- d->m_projects.removeOne(pro);
-
- if (pro == d->m_startupProject)
- changeStartupProject = true;
-
- FolderNavigationWidgetFactory::removeRootDirectory(projectFolderId(pro));
- disconnect(pro, nullptr, m_instance, nullptr);
- emit m_instance->projectRemoved(pro);
- }
-
- if (changeStartupProject)
- setStartupProject(hasProjects() ? projects().first() : nullptr);
-
- qDeleteAll(remove);
-}
-
-/*!
- Lets other plugins store persistent values within the session file.
-*/
-
-void SessionManager::setValue(const QString &name, const QVariant &value)
-{
- if (d->m_values.value(name) == value)
- return;
- d->m_values.insert(name, value);
-}
-
-QVariant SessionManager::value(const QString &name)
-{
- auto it = d->m_values.constFind(name);
- return (it == d->m_values.constEnd()) ? QVariant() : *it;
-}
-
-QString SessionManager::activeSession()
-{
- return d->m_sessionName;
-}
-
-QStringList SessionManager::sessions()
-{
- if (d->m_sessions.isEmpty()) {
- // We are not initialized yet, so do that now
- const FilePaths sessionFiles =
- ICore::userResourcePath().dirEntries({{"*qws"}}, QDir::Time | QDir::Reversed);
- const QVariantMap lastActiveTimes = ICore::settings()->value(LAST_ACTIVE_TIMES_KEY).toMap();
- for (const FilePath &file : sessionFiles) {
- const QString &name = file.completeBaseName();
- d->m_sessionDateTimes.insert(name, file.lastModified());
- const auto lastActiveTime = lastActiveTimes.find(name);
- d->m_lastActiveTimes.insert(name, lastActiveTime != lastActiveTimes.end()
- ? lastActiveTime->toDateTime()
- : file.lastModified());
- if (name != QLatin1String(DEFAULT_SESSION))
- d->m_sessions << name;
- }
- d->m_sessions.prepend(QLatin1String(DEFAULT_SESSION));
- }
- return d->m_sessions;
-}
-
-QDateTime SessionManager::sessionDateTime(const QString &session)
-{
- return d->m_sessionDateTimes.value(session);
-}
-
-QDateTime SessionManager::lastActiveTime(const QString &session)
-{
- return d->m_lastActiveTimes.value(session);
-}
-
-FilePath SessionManager::sessionNameToFileName(const QString &session)
-{
- return ICore::userResourcePath(session + ".qws");
-}
-
-/*!
- Creates \a session, but does not actually create the file.
-*/
-
-bool SessionManager::createSession(const QString &session)
-{
- if (sessions().contains(session))
- return false;
- Q_ASSERT(d->m_sessions.size() > 0);
- d->m_sessions.insert(1, session);
- d->m_lastActiveTimes.insert(session, QDateTime::currentDateTime());
- return true;
-}
-
-bool SessionManager::renameSession(const QString &original, const QString &newName)
-{
- if (!cloneSession(original, newName))
- return false;
- if (original == activeSession())
- loadSession(newName);
- emit instance()->sessionRenamed(original, newName);
- return deleteSession(original);
-}
-
-
-/*!
- \brief Shows a dialog asking the user to confirm deleting the session \p session
-*/
-bool SessionManager::confirmSessionDelete(const QStringList &sessions)
-{
- const QString title = sessions.size() == 1 ? Tr::tr("Delete Session") : Tr::tr("Delete Sessions");
- const QString question = sessions.size() == 1
- ? Tr::tr("Delete session %1?").arg(sessions.first())
- : Tr::tr("Delete these sessions?\n %1").arg(sessions.join("\n "));
- return QMessageBox::question(ICore::dialogParent(),
- title,
- question,
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes;
-}
-
-/*!
- Deletes \a session name from session list and the file from disk.
-*/
-bool SessionManager::deleteSession(const QString &session)
-{
- if (!d->m_sessions.contains(session))
- return false;
- d->m_sessions.removeOne(session);
- d->m_lastActiveTimes.remove(session);
- emit instance()->sessionRemoved(session);
- FilePath sessionFile = sessionNameToFileName(session);
- if (sessionFile.exists())
- return sessionFile.removeFile();
- return false;
-}
-
-void SessionManager::deleteSessions(const QStringList &sessions)
-{
- for (const QString &session : sessions)
- deleteSession(session);
-}
-
-bool SessionManager::cloneSession(const QString &original, const QString &clone)
-{
- if (!d->m_sessions.contains(original))
- return false;
-
- FilePath sessionFile = sessionNameToFileName(original);
- // If the file does not exist, we can still clone
- if (!sessionFile.exists() || sessionFile.copyFile(sessionNameToFileName(clone))) {
- d->m_sessions.insert(1, clone);
- d->m_sessionDateTimes.insert(clone, sessionNameToFileName(clone).lastModified());
- return true;
- }
- return false;
-}
-
-void SessionManagerPrivate::restoreValues(const PersistentSettingsReader &reader)
-{
- const QStringList keys = reader.restoreValue(QLatin1String("valueKeys")).toStringList();
- for (const QString &key : keys) {
- QVariant value = reader.restoreValue(QLatin1String("value-") + key);
- m_values.insert(key, value);
- }
-}
-
-void SessionManagerPrivate::restoreDependencies(const PersistentSettingsReader &reader)
-{
- QMap<QString, QVariant> depMap = reader.restoreValue(QLatin1String("ProjectDependencies")).toMap();
- auto i = depMap.constBegin();
- while (i != depMap.constEnd()) {
- const QString &key = i.key();
- FilePaths values;
- const QStringList valueList = i.value().toStringList();
- for (const QString &value : valueList)
- values << FilePath::fromString(value);
- m_depMap.insert(FilePath::fromString(key), values);
- ++i;
- }
-}
-
-void SessionManagerPrivate::askUserAboutFailedProjects()
-{
- FilePaths failedProjects = m_failedProjects;
- if (!failedProjects.isEmpty()) {
- QString fileList = FilePath::formatFilePaths(failedProjects, "<br>");
- QMessageBox box(QMessageBox::Warning,
- Tr::tr("Failed to restore project files"),
- Tr::tr("Could not restore the following project files:<br><b>%1</b>").
- arg(fileList));
- auto keepButton = new QPushButton(Tr::tr("Keep projects in Session"), &box);
- auto removeButton = new QPushButton(Tr::tr("Remove projects from Session"), &box);
- box.addButton(keepButton, QMessageBox::AcceptRole);
- box.addButton(removeButton, QMessageBox::DestructiveRole);
-
- box.exec();
-
- if (box.clickedButton() == removeButton)
- m_failedProjects.clear();
- }
-}
-
-void SessionManagerPrivate::restoreStartupProject(const PersistentSettingsReader &reader)
-{
- const FilePath startupProject = FilePath::fromSettings(reader.restoreValue("StartupProject"));
- if (!startupProject.isEmpty()) {
- for (Project *pro : std::as_const(m_projects)) {
- if (pro->projectFilePath() == startupProject) {
- m_instance->setStartupProject(pro);
- break;
- }
- }
- }
- if (!m_startupProject) {
- if (!startupProject.isEmpty())
- qWarning() << "Could not find startup project" << startupProject;
- if (hasProjects())
- m_instance->setStartupProject(m_projects.first());
- }
-}
-
-void SessionManagerPrivate::restoreEditors(const PersistentSettingsReader &reader)
-{
- const QVariant editorsettings = reader.restoreValue(QLatin1String("EditorSettings"));
- if (editorsettings.isValid()) {
- EditorManager::restoreState(QByteArray::fromBase64(editorsettings.toByteArray()));
- sessionLoadingProgress();
- }
-}
-
-/*!
- Loads a session, takes a session name (not filename).
-*/
-void SessionManagerPrivate::restoreProjects(const FilePaths &fileList)
-{
- // indirectly adds projects to session
- // Keep projects that failed to load in the session!
- m_failedProjects = fileList;
- if (!fileList.isEmpty()) {
- ProjectExplorerPlugin::OpenProjectResult result = ProjectExplorerPlugin::openProjects(fileList);
- if (!result)
- ProjectExplorerPlugin::showOpenProjectError(result);
- const QList<Project *> projects = result.projects();
- for (const Project *p : projects)
- m_failedProjects.removeAll(p->projectFilePath());
- }
-}
-
-/*
- * ========== Notes on storing and loading the default session ==========
- * The default session comes in two flavors: implicit and explicit. The implicit one,
- * also referred to as "default virgin" in the code base, is the one that is active
- * at start-up, if no session has been explicitly loaded due to command-line arguments
- * or the "restore last session" setting in the session manager.
- * The implicit default session silently turns into the explicit default session
- * by loading a project or a file or changing settings in the Dependencies panel. The explicit
- * default session can also be loaded by the user via the Welcome Screen.
- * This mechanism somewhat complicates the handling of session-specific settings such as
- * the ones in the task pane: Users expect that changes they make there become persistent, even
- * when they are in the implicit default session. However, we can't just blindly store
- * the implicit default session, because then we'd overwrite the project list of the explicit
- * default session. Therefore, we use the following logic:
- * - Upon start-up, if no session is to be explicitly loaded, we restore the parts of the
- * explicit default session that are not related to projects, editors etc; the
- * "general settings" of the session, so to speak.
- * - When storing the implicit default session, we overwrite only these "general settings"
- * of the explicit default session and keep the others as they are.
- * - When switching from the implicit to the explicit default session, we keep the
- * "general settings" and load everything else from the session file.
- * This guarantees that user changes are properly transferred and nothing gets lost from
- * either the implicit or the explicit default session.
- *
- */
-bool SessionManager::loadSession(const QString &session, bool initial)
-{
- const bool loadImplicitDefault = session.isEmpty();
- const bool switchFromImplicitToExplicitDefault = session == DEFAULT_SESSION
- && d->m_sessionName == DEFAULT_SESSION && !initial;
-
- // Do nothing if we have that session already loaded,
- // exception if the session is the default virgin session
- // we still want to be able to load the default session
- if (session == d->m_sessionName && !isDefaultVirgin())
- return true;
-
- if (!loadImplicitDefault && !sessions().contains(session))
- return false;
-
- FilePaths fileList;
- // Try loading the file
- FilePath fileName = sessionNameToFileName(loadImplicitDefault ? DEFAULT_SESSION : session);
- PersistentSettingsReader reader;
- if (fileName.exists()) {
- if (!reader.load(fileName)) {
- QMessageBox::warning(ICore::dialogParent(), Tr::tr("Error while restoring session"),
- Tr::tr("Could not restore session %1").arg(fileName.toUserOutput()));
-
- return false;
- }
-
- if (loadImplicitDefault) {
- d->restoreValues(reader);
- emit m_instance->sessionLoaded(DEFAULT_SESSION);
- return true;
- }
-
- fileList = FileUtils::toFilePathList(reader.restoreValue("ProjectList").toStringList());
- } else if (loadImplicitDefault) {
- return true;
- }
-
- d->m_loadingSession = true;
-
- // Allow everyone to set something in the session and before saving
- emit m_instance->aboutToUnloadSession(d->m_sessionName);
-
- if (!save()) {
- d->m_loadingSession = false;
- return false;
- }
-
- // Clean up
- if (!EditorManager::closeAllEditors()) {
- d->m_loadingSession = false;
- return false;
- }
-
- // find a list of projects to close later
- const QList<Project *> projectsToRemove = Utils::filtered(projects(), [&fileList](Project *p) {
- return !fileList.contains(p->projectFilePath());
- });
- const QList<Project *> openProjects = projects();
- const FilePaths projectPathsToLoad = Utils::filtered(fileList, [&openProjects](const FilePath &path) {
- return !Utils::contains(openProjects, [&path](Project *p) {
- return p->projectFilePath() == path;
- });
- });
- d->m_failedProjects.clear();
- d->m_depMap.clear();
- if (!switchFromImplicitToExplicitDefault)
- d->m_values.clear();
- d->m_casadeSetActive = false;
-
- d->m_sessionName = session;
- delete d->m_writer;
- d->m_writer = nullptr;
- EditorManager::updateWindowTitles();
-
- if (fileName.exists()) {
- d->m_virginSession = false;
-
- ProgressManager::addTask(d->m_future.future(), Tr::tr("Loading Session"),
- "ProjectExplorer.SessionFile.Load");
-
- d->m_future.setProgressRange(0, 1);
- d->m_future.setProgressValue(0);
-
- if (!switchFromImplicitToExplicitDefault)
- d->restoreValues(reader);
- emit m_instance->aboutToLoadSession(session);
-
- // retrieve all values before the following code could change them again
- Id modeId = Id::fromSetting(value(QLatin1String("ActiveMode")));
- if (!modeId.isValid())
- modeId = Id(Core::Constants::MODE_EDIT);
-
- QColor c = QColor(reader.restoreValue(QLatin1String("Color")).toString());
- if (c.isValid())
- StyleHelper::setBaseColor(c);
-
- d->m_future.setProgressRange(0, projectPathsToLoad.count() + 1/*initialization above*/ + 1/*editors*/);
- d->m_future.setProgressValue(1);
- QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
-
- d->restoreProjects(projectPathsToLoad);
- d->sessionLoadingProgress();
- d->restoreDependencies(reader);
- d->restoreStartupProject(reader);
-
- removeProjects(projectsToRemove); // only remove old projects now that the startup project is set!
-
- d->restoreEditors(reader);
-
- d->m_future.reportFinished();
- d->m_future = QFutureInterface<void>();
-
- // Fall back to Project mode if the startup project is unconfigured and
- // use the mode saved in the session otherwise
- if (d->m_startupProject && d->m_startupProject->needsConfiguration())
- modeId = Id(Constants::MODE_SESSION);
-
- ModeManager::activateMode(modeId);
- ModeManager::setFocusToCurrentMode();
- } else {
- removeProjects(projects());
- ModeManager::activateMode(Id(Core::Constants::MODE_EDIT));
- ModeManager::setFocusToCurrentMode();
- }
-
- d->m_casadeSetActive = reader.restoreValue(QLatin1String("CascadeSetActive"), false).toBool();
- d->m_lastActiveTimes.insert(session, QDateTime::currentDateTime());
-
- emit m_instance->sessionLoaded(session);
-
- // Starts a event loop, better do that at the very end
- d->askUserAboutFailedProjects();
- d->m_loadingSession = false;
- return true;
-}
-
-/*!
- Returns the last session that was opened by the user.
-*/
-QString SessionManager::lastSession()
-{
- return ICore::settings()->value(Constants::LASTSESSION_KEY).toString();
-}
-
-/*!
- Returns the session that was active when Qt Creator was last closed, if any.
-*/
-QString SessionManager::startupSession()
-{
- return ICore::settings()->value(Constants::STARTUPSESSION_KEY).toString();
-}
-
-void SessionManager::reportProjectLoadingProgress()
-{
- d->sessionLoadingProgress();
-}
-
-void SessionManager::markSessionFileDirty()
-{
- d->m_virginSession = false;
-}
-
-void SessionManagerPrivate::sessionLoadingProgress()
-{
- m_future.setProgressValue(m_future.progressValue() + 1);
- QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
-}
-
-FilePaths SessionManager::projectsForSessionName(const QString &session)
-{
- const FilePath fileName = sessionNameToFileName(session);
- PersistentSettingsReader reader;
- if (fileName.exists()) {
- if (!reader.load(fileName)) {
- qWarning() << "Could not restore session" << fileName.toUserOutput();
- return {};
- }
- }
- return transform(reader.restoreValue(QLatin1String("ProjectList")).toStringList(),
- &FilePath::fromUserInput);
-}
-
-#ifdef WITH_TESTS
-
-void ProjectExplorerPlugin::testSessionSwitch()
-{
- QVERIFY(SessionManager::createSession("session1"));
- QVERIFY(SessionManager::createSession("session2"));
- QTemporaryFile cppFile("main.cpp");
- QVERIFY(cppFile.open());
- cppFile.close();
- QTemporaryFile projectFile1("XXXXXX.pro");
- QTemporaryFile projectFile2("XXXXXX.pro");
- struct SessionSpec {
- SessionSpec(const QString &n, QTemporaryFile &f) : name(n), projectFile(f) {}
- const QString name;
- QTemporaryFile &projectFile;
- };
- std::vector<SessionSpec> sessionSpecs{SessionSpec("session1", projectFile1),
- SessionSpec("session2", projectFile2)};
- for (const SessionSpec &sessionSpec : sessionSpecs) {
- static const QByteArray proFileContents
- = "TEMPLATE = app\n"
- "CONFIG -= qt\n"
- "SOURCES = " + cppFile.fileName().toLocal8Bit();
- QVERIFY(sessionSpec.projectFile.open());
- sessionSpec.projectFile.write(proFileContents);
- sessionSpec.projectFile.close();
- QVERIFY(SessionManager::loadSession(sessionSpec.name));
- const OpenProjectResult openResult
- = ProjectExplorerPlugin::openProject(
- FilePath::fromString(sessionSpec.projectFile.fileName()));
- if (openResult.errorMessage().contains("text/plain"))
- QSKIP("This test requires the presence of QmakeProjectManager to be fully functional");
- QVERIFY(openResult);
- QCOMPARE(openResult.projects().count(), 1);
- QVERIFY(openResult.project());
- QCOMPARE(SessionManager::projects().count(), 1);
- }
- for (int i = 0; i < 30; ++i) {
- QVERIFY(SessionManager::loadSession("session1"));
- QCOMPARE(SessionManager::activeSession(), "session1");
- QCOMPARE(SessionManager::projects().count(), 1);
- QVERIFY(SessionManager::loadSession("session2"));
- QCOMPARE(SessionManager::activeSession(), "session2");
- QCOMPARE(SessionManager::projects().count(), 1);
- }
- QVERIFY(SessionManager::loadSession("session1"));
- SessionManager::closeAllProjects();
- QVERIFY(SessionManager::loadSession("session2"));
- SessionManager::closeAllProjects();
- QVERIFY(SessionManager::deleteSession("session1"));
- QVERIFY(SessionManager::deleteSession("session2"));
-}
-
-#endif // WITH_TESTS
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h
deleted file mode 100644
index a29e478046..0000000000
--- a/src/plugins/projectexplorer/session.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "projectexplorer_export.h"
-
-#include <utils/id.h>
-#include <utils/persistentsettings.h>
-
-#include <QDateTime>
-#include <QString>
-#include <QStringList>
-
-namespace Core { class IEditor; }
-
-namespace ProjectExplorer {
-
-class Project;
-class Target;
-class BuildConfiguration;
-class BuildSystem;
-class DeployConfiguration;
-class RunConfiguration;
-
-enum class SetActive { Cascade, NoCascade };
-
-class PROJECTEXPLORER_EXPORT SessionManager : public QObject
-{
- Q_OBJECT
-
-public:
- explicit SessionManager(QObject *parent = nullptr);
- ~SessionManager() override;
-
- static SessionManager *instance();
-
- // higher level session management
- static QString activeSession();
- static QString lastSession();
- static QString startupSession();
- static QStringList sessions();
- static QDateTime sessionDateTime(const QString &session);
- static QDateTime lastActiveTime(const QString &session);
-
- static bool createSession(const QString &session);
-
- static bool confirmSessionDelete(const QStringList &sessions);
- static bool deleteSession(const QString &session);
- static void deleteSessions(const QStringList &sessions);
-
- static bool cloneSession(const QString &original, const QString &clone);
- static bool renameSession(const QString &original, const QString &newName);
-
- static bool loadSession(const QString &session, bool initial = false);
-
- static bool save();
- static void closeAllProjects();
-
- static void addProject(Project *project);
- static void removeProject(Project *project);
- static void removeProjects(const QList<Project *> &remove);
-
- static void setStartupProject(Project *startupProject);
-
- static QList<Project *> dependencies(const Project *project);
- static bool hasDependency(const Project *project, const Project *depProject);
- static bool canAddDependency(const Project *project, const Project *depProject);
- static bool addDependency(Project *project, Project *depProject);
- static void removeDependency(Project *project, Project *depProject);
-
- static bool isProjectConfigurationCascading();
- static void setProjectConfigurationCascading(bool b);
-
- static void setActiveTarget(Project *p, Target *t, SetActive cascade);
- static void setActiveBuildConfiguration(Target *t, BuildConfiguration *bc, SetActive cascade);
- static void setActiveDeployConfiguration(Target *t, DeployConfiguration *dc, SetActive cascade);
-
- static Utils::FilePath sessionNameToFileName(const QString &session);
- static Project *startupProject();
- static Target *startupTarget();
- static BuildSystem *startupBuildSystem();
- static RunConfiguration *startupRunConfiguration();
-
- static const QList<Project *> projects();
- static bool hasProjects();
- static bool hasProject(Project *p);
-
- static bool isDefaultVirgin();
- static bool isDefaultSession(const QString &session);
-
- // Let other plugins store persistent values within the session file
- static void setValue(const QString &name, const QVariant &value);
- static QVariant value(const QString &name);
-
- // NBS rewrite projectOrder (dependency management)
- static QList<Project *> projectOrder(const Project *project = nullptr);
-
- static Project *projectForFile(const Utils::FilePath &fileName);
- static Project *projectWithProjectFilePath(const Utils::FilePath &filePath);
-
- static Utils::FilePaths projectsForSessionName(const QString &session);
-
- static void reportProjectLoadingProgress();
- static bool loadingSession();
-
-signals:
- void targetAdded(ProjectExplorer::Target *target);
- void targetRemoved(ProjectExplorer::Target *target);
- void projectAdded(ProjectExplorer::Project *project);
- void aboutToRemoveProject(ProjectExplorer::Project *project);
- void projectDisplayNameChanged(ProjectExplorer::Project *project);
- void projectRemoved(ProjectExplorer::Project *project);
-
- void startupProjectChanged(ProjectExplorer::Project *project);
-
- void aboutToUnloadSession(QString sessionName);
- void aboutToLoadSession(QString sessionName);
- void sessionLoaded(QString sessionName);
- void aboutToSaveSession();
- void dependencyChanged(ProjectExplorer::Project *a, ProjectExplorer::Project *b);
-
- void sessionRenamed(const QString &oldName, const QString &newName);
- void sessionRemoved(const QString &name);
-
- // for tests only
- void projectFinishedParsing(ProjectExplorer::Project *project);
-
-private:
- static void saveActiveMode(Utils::Id mode);
- static void configureEditor(Core::IEditor *editor, const QString &fileName);
- static void markSessionFileDirty();
- static void configureEditors(Project *project);
-};
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/sessiondialog.cpp b/src/plugins/projectexplorer/sessiondialog.cpp
deleted file mode 100644
index 745a876230..0000000000
--- a/src/plugins/projectexplorer/sessiondialog.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "sessiondialog.h"
-
-#include "projectexplorertr.h"
-#include "session.h"
-#include "sessionview.h"
-
-#include <utils/algorithm.h>
-#include <utils/layoutbuilder.h>
-
-#include <QCheckBox>
-#include <QDialogButtonBox>
-#include <QInputDialog>
-#include <QLabel>
-#include <QPushButton>
-#include <QValidator>
-
-namespace ProjectExplorer::Internal {
-
-class SessionValidator : public QValidator
-{
-public:
- SessionValidator(QObject *parent, const QStringList &sessions);
- void fixup(QString & input) const override;
- QValidator::State validate(QString & input, int & pos) const override;
-private:
- QStringList m_sessions;
-};
-
-SessionValidator::SessionValidator(QObject *parent, const QStringList &sessions)
- : QValidator(parent), m_sessions(sessions)
-{
-}
-
-QValidator::State SessionValidator::validate(QString &input, int &pos) const
-{
- Q_UNUSED(pos)
-
- if (input.contains(QLatin1Char('/'))
- || input.contains(QLatin1Char(':'))
- || input.contains(QLatin1Char('\\'))
- || input.contains(QLatin1Char('?'))
- || input.contains(QLatin1Char('*')))
- return QValidator::Invalid;
-
- if (m_sessions.contains(input))
- return QValidator::Intermediate;
- else
- return QValidator::Acceptable;
-}
-
-void SessionValidator::fixup(QString &input) const
-{
- int i = 2;
- QString copy;
- do {
- copy = input + QLatin1String(" (") + QString::number(i) + QLatin1Char(')');
- ++i;
- } while (m_sessions.contains(copy));
- input = copy;
-}
-
-SessionNameInputDialog::SessionNameInputDialog(QWidget *parent)
- : QDialog(parent)
-{
- m_newSessionLineEdit = new QLineEdit(this);
- m_newSessionLineEdit->setValidator(new SessionValidator(this, SessionManager::sessions()));
-
- auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
- m_okButton = buttons->button(QDialogButtonBox::Ok);
- m_switchToButton = new QPushButton;
- m_switchToButton->setDefault(true);
- buttons->addButton(m_switchToButton, QDialogButtonBox::AcceptRole);
- connect(m_switchToButton, &QPushButton::clicked, this, [this] {
- m_usedSwitchTo = true;
- });
-
- using namespace Utils::Layouting;
- Column {
- Tr::tr("Enter the name of the session:"),
- m_newSessionLineEdit,
- buttons,
- }.attachTo(this);
-
- connect(m_newSessionLineEdit, &QLineEdit::textChanged, [this](const QString &text) {
- m_okButton->setEnabled(!text.isEmpty());
- m_switchToButton->setEnabled(!text.isEmpty());
- });
- m_okButton->setEnabled(false);
- m_switchToButton->setEnabled(false);
-
- connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
-}
-
-void SessionNameInputDialog::setActionText(const QString &actionText, const QString &openActionText)
-{
- m_okButton->setText(actionText);
- m_switchToButton->setText(openActionText);
-}
-
-void SessionNameInputDialog::setValue(const QString &value)
-{
- m_newSessionLineEdit->setText(value);
-}
-
-QString SessionNameInputDialog::value() const
-{
- return m_newSessionLineEdit->text();
-}
-
-bool SessionNameInputDialog::isSwitchToRequested() const
-{
- return m_usedSwitchTo;
-}
-
-SessionDialog::SessionDialog(QWidget *parent) : QDialog(parent)
-{
- setObjectName("ProjectExplorer.SessionDialog");
- resize(550, 400);
- setWindowTitle(Tr::tr("Session Manager"));
-
-
- auto sessionView = new SessionView(this);
- sessionView->setObjectName("sessionView");
- sessionView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- sessionView->setActivationMode(Utils::DoubleClickActivation);
-
- auto createNewButton = new QPushButton(Tr::tr("&New"));
- createNewButton->setObjectName("btCreateNew");
-
- m_openButton = new QPushButton(Tr::tr("&Open"));
- m_openButton->setObjectName("btOpen");
- m_renameButton = new QPushButton(Tr::tr("&Rename"));
- m_cloneButton = new QPushButton(Tr::tr("C&lone"));
- m_deleteButton = new QPushButton(Tr::tr("&Delete"));
-
- m_autoLoadCheckBox = new QCheckBox(Tr::tr("Restore last session on startup"));
-
- auto buttonBox = new QDialogButtonBox(this);
- buttonBox->setStandardButtons(QDialogButtonBox::Close);
-
- m_openButton->setDefault(true);
-
- // FIXME: Simplify translator's work.
- auto whatsASessionLabel = new QLabel(
- Tr::tr("<a href=\"qthelp://org.qt-project.qtcreator/doc/creator-project-managing-sessions.html\">"
- "What is a Session?</a>"));
- whatsASessionLabel->setOpenExternalLinks(true);
-
- using namespace Utils::Layouting;
-
- Column {
- Row {
- sessionView,
- Column {
- createNewButton,
- m_openButton,
- m_renameButton,
- m_cloneButton,
- m_deleteButton,
- st
- }
- },
- m_autoLoadCheckBox,
- hr,
- Row { whatsASessionLabel, buttonBox },
- }.attachTo(this);
-
- connect(createNewButton, &QAbstractButton::clicked,
- sessionView, &SessionView::createNewSession);
- connect(m_openButton, &QAbstractButton::clicked,
- sessionView, &SessionView::switchToCurrentSession);
- connect(m_renameButton, &QAbstractButton::clicked,
- sessionView, &SessionView::renameCurrentSession);
- connect(m_cloneButton, &QAbstractButton::clicked,
- sessionView, &SessionView::cloneCurrentSession);
- connect(m_deleteButton, &QAbstractButton::clicked,
- sessionView, &SessionView::deleteSelectedSessions);
- connect(sessionView, &SessionView::sessionActivated,
- sessionView, &SessionView::switchToCurrentSession);
-
- connect(sessionView, &SessionView::sessionsSelected,
- this, &SessionDialog::updateActions);
- connect(sessionView, &SessionView::sessionSwitched,
- this, &QDialog::reject);
-
- connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
-}
-
-void SessionDialog::setAutoLoadSession(bool check)
-{
- m_autoLoadCheckBox->setChecked(check);
-}
-
-bool SessionDialog::autoLoadSession() const
-{
- return m_autoLoadCheckBox->checkState() == Qt::Checked;
-}
-
-void SessionDialog::updateActions(const QStringList &sessions)
-{
- if (sessions.isEmpty()) {
- m_openButton->setEnabled(false);
- m_renameButton->setEnabled(false);
- m_cloneButton->setEnabled(false);
- m_deleteButton->setEnabled(false);
- return;
- }
- const bool defaultIsSelected = sessions.contains("default");
- const bool activeIsSelected = Utils::anyOf(sessions, [](const QString &session) {
- return session == SessionManager::activeSession();
- });
- m_openButton->setEnabled(sessions.size() == 1);
- m_renameButton->setEnabled(sessions.size() == 1 && !defaultIsSelected);
- m_cloneButton->setEnabled(sessions.size() == 1);
- m_deleteButton->setEnabled(!defaultIsSelected && !activeIsSelected);
-}
-
-} // ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/sessiondialog.h b/src/plugins/projectexplorer/sessiondialog.h
deleted file mode 100644
index 56cab430ea..0000000000
--- a/src/plugins/projectexplorer/sessiondialog.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <QString>
-#include <QDialog>
-
-QT_BEGIN_NAMESPACE
-class QCheckBox;
-class QLineEdit;
-class QPushButton;
-QT_END_NAMESPACE
-
-namespace ProjectExplorer::Internal {
-
-class SessionDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit SessionDialog(QWidget *parent = nullptr);
-
- void setAutoLoadSession(bool);
- bool autoLoadSession() const;
-
-private:
- void updateActions(const QStringList &sessions);
-
- QPushButton *m_openButton;
- QPushButton *m_renameButton;
- QPushButton *m_cloneButton;
- QPushButton *m_deleteButton;
- QCheckBox *m_autoLoadCheckBox;
-};
-
-class SessionNameInputDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit SessionNameInputDialog(QWidget *parent);
-
- void setActionText(const QString &actionText, const QString &openActionText);
- void setValue(const QString &value);
- QString value() const;
- bool isSwitchToRequested() const;
-
-private:
- QLineEdit *m_newSessionLineEdit = nullptr;
- QPushButton *m_switchToButton = nullptr;
- QPushButton *m_okButton = nullptr;
- bool m_usedSwitchTo = false;
-};
-
-} // ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/sessionmodel.cpp b/src/plugins/projectexplorer/sessionmodel.cpp
deleted file mode 100644
index d8c9aa935e..0000000000
--- a/src/plugins/projectexplorer/sessionmodel.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "sessionmodel.h"
-
-#include "projectexplorertr.h"
-#include "session.h"
-#include "sessiondialog.h"
-
-#include <coreplugin/actionmanager/actionmanager.h>
-
-#include <utils/algorithm.h>
-#include <utils/fileutils.h>
-#include <utils/stringutils.h>
-
-#include <QFileInfo>
-#include <QDir>
-
-using namespace Core;
-using namespace Utils;
-
-namespace ProjectExplorer {
-namespace Internal {
-
-SessionModel::SessionModel(QObject *parent)
- : QAbstractTableModel(parent)
-{
- m_sortedSessions = SessionManager::sessions();
- connect(SessionManager::instance(), &SessionManager::sessionLoaded,
- this, &SessionModel::resetSessions);
-}
-
-int SessionModel::indexOfSession(const QString &session)
-{
- return m_sortedSessions.indexOf(session);
-}
-
-QString SessionModel::sessionAt(int row) const
-{
- return m_sortedSessions.value(row, QString());
-}
-
-QVariant SessionModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
- QVariant result;
- if (orientation == Qt::Horizontal) {
- switch (role) {
- case Qt::DisplayRole:
- switch (section) {
- case 0: result = Tr::tr("Session");
- break;
- case 1: result = Tr::tr("Last Modified");
- break;
- } // switch (section)
- break;
- } // switch (role) {
- }
- return result;
-}
-
-int SessionModel::columnCount(const QModelIndex &) const
-{
- static int sectionCount = 0;
- if (sectionCount == 0) {
- // headers sections defining possible columns
- while (!headerData(sectionCount, Qt::Horizontal, Qt::DisplayRole).isNull())
- sectionCount++;
- }
-
- return sectionCount;
-}
-
-int SessionModel::rowCount(const QModelIndex &) const
-{
- return m_sortedSessions.count();
-}
-
-QStringList pathsToBaseNames(const FilePaths &paths)
-{
- return Utils::transform(paths, &FilePath::completeBaseName);
-}
-
-QStringList pathsWithTildeHomePath(const FilePaths &paths)
-{
- return Utils::transform(paths, &FilePath::withTildeHomePath);
-}
-
-QVariant SessionModel::data(const QModelIndex &index, int role) const
-{
- QVariant result;
- if (index.isValid()) {
- QString sessionName = m_sortedSessions.at(index.row());
-
- switch (role) {
- case Qt::DisplayRole:
- switch (index.column()) {
- case 0: result = sessionName;
- break;
- case 1: result = SessionManager::sessionDateTime(sessionName);
- break;
- } // switch (section)
- break;
- case Qt::FontRole: {
- QFont font;
- if (SessionManager::isDefaultSession(sessionName))
- font.setItalic(true);
- else
- font.setItalic(false);
- if (SessionManager::activeSession() == sessionName && !SessionManager::isDefaultVirgin())
- font.setBold(true);
- else
- font.setBold(false);
- result = font;
- } break;
- case DefaultSessionRole:
- result = SessionManager::isDefaultSession(sessionName);
- break;
- case LastSessionRole:
- result = SessionManager::lastSession() == sessionName;
- break;
- case ActiveSessionRole:
- result = SessionManager::activeSession() == sessionName;
- break;
- case ProjectsPathRole:
- result = pathsWithTildeHomePath(SessionManager::projectsForSessionName(sessionName));
- break;
- case ProjectsDisplayRole:
- result = pathsToBaseNames(SessionManager::projectsForSessionName(sessionName));
- break;
- case ShortcutRole: {
- const Id sessionBase = SESSION_BASE_ID;
- if (Command *cmd = ActionManager::command(sessionBase.withSuffix(index.row() + 1)))
- result = cmd->keySequence().toString(QKeySequence::NativeText);
- } break;
- } // switch (role)
- }
-
- return result;
-}
-
-QHash<int, QByteArray> SessionModel::roleNames() const
-{
- static const QHash<int, QByteArray> extraRoles{
- {Qt::DisplayRole, "sessionName"},
- {DefaultSessionRole, "defaultSession"},
- {ActiveSessionRole, "activeSession"},
- {LastSessionRole, "lastSession"},
- {ProjectsPathRole, "projectsPath"},
- {ProjectsDisplayRole, "projectsName"}
- };
- QHash<int, QByteArray> roles = QAbstractTableModel::roleNames();
- Utils::addToHash(&roles, extraRoles);
- return roles;
-}
-
-void SessionModel::sort(int column, Qt::SortOrder order)
-{
- beginResetModel();
- const auto cmp = [column, order](const QString &s1, const QString &s2) {
- bool isLess;
- if (column == 0) {
- if (s1 == s2)
- return false;
- isLess = s1 < s2;
- }
- else {
- const auto s1time = SessionManager::sessionDateTime(s1);
- const auto s2time = SessionManager::sessionDateTime(s2);
- if (s1time == s2time)
- return false;
- isLess = s1time < s2time;
- }
- if (order == Qt::DescendingOrder)
- isLess = !isLess;
- return isLess;
- };
- Utils::sort(m_sortedSessions, cmp);
- m_currentSortColumn = column;
- m_currentSortOrder = order;
- endResetModel();
-}
-
-bool SessionModel::isDefaultVirgin() const
-{
- return SessionManager::isDefaultVirgin();
-}
-
-void SessionModel::resetSessions()
-{
- beginResetModel();
- m_sortedSessions = SessionManager::sessions();
- endResetModel();
-}
-
-void SessionModel::newSession(QWidget *parent)
-{
- SessionNameInputDialog sessionInputDialog(parent);
- sessionInputDialog.setWindowTitle(Tr::tr("New Session Name"));
- sessionInputDialog.setActionText(Tr::tr("&Create"), Tr::tr("Create and &Open"));
-
- runSessionNameInputDialog(&sessionInputDialog, [](const QString &newName) {
- SessionManager::createSession(newName);
- });
-}
-
-void SessionModel::cloneSession(QWidget *parent, const QString &session)
-{
- SessionNameInputDialog sessionInputDialog(parent);
- sessionInputDialog.setWindowTitle(Tr::tr("New Session Name"));
- sessionInputDialog.setActionText(Tr::tr("&Clone"), Tr::tr("Clone and &Open"));
- sessionInputDialog.setValue(session + " (2)");
-
- runSessionNameInputDialog(&sessionInputDialog, [session](const QString &newName) {
- SessionManager::cloneSession(session, newName);
- });
-}
-
-void SessionModel::deleteSessions(const QStringList &sessions)
-{
- if (!SessionManager::confirmSessionDelete(sessions))
- return;
- beginResetModel();
- SessionManager::deleteSessions(sessions);
- m_sortedSessions = SessionManager::sessions();
- sort(m_currentSortColumn, m_currentSortOrder);
- endResetModel();
-}
-
-void SessionModel::renameSession(QWidget *parent, const QString &session)
-{
- SessionNameInputDialog sessionInputDialog(parent);
- sessionInputDialog.setWindowTitle(Tr::tr("Rename Session"));
- sessionInputDialog.setActionText(Tr::tr("&Rename"), Tr::tr("Rename and &Open"));
- sessionInputDialog.setValue(session);
-
- runSessionNameInputDialog(&sessionInputDialog, [session](const QString &newName) {
- SessionManager::renameSession(session, newName);
- });
-}
-
-void SessionModel::switchToSession(const QString &session)
-{
- SessionManager::loadSession(session);
- emit sessionSwitched();
-}
-
-void SessionModel::runSessionNameInputDialog(SessionNameInputDialog *sessionInputDialog, std::function<void(const QString &)> createSession)
-{
- if (sessionInputDialog->exec() == QDialog::Accepted) {
- QString newSession = sessionInputDialog->value();
- if (newSession.isEmpty() || SessionManager::sessions().contains(newSession))
- return;
- beginResetModel();
- createSession(newSession);
- m_sortedSessions = SessionManager::sessions();
- endResetModel();
- sort(m_currentSortColumn, m_currentSortOrder);
-
- if (sessionInputDialog->isSwitchToRequested())
- switchToSession(newSession);
- emit sessionCreated(newSession);
- }
-}
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/sessionmodel.h b/src/plugins/projectexplorer/sessionmodel.h
deleted file mode 100644
index 82f1994210..0000000000
--- a/src/plugins/projectexplorer/sessionmodel.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <QAbstractTableModel>
-
-#include <functional>
-
-namespace ProjectExplorer {
-namespace Internal {
-
-const char SESSION_BASE_ID[] = "Welcome.OpenSession";
-
-class SessionNameInputDialog;
-
-class SessionModel : public QAbstractTableModel
-{
- Q_OBJECT
-
-public:
- enum {
- DefaultSessionRole = Qt::UserRole+1,
- LastSessionRole,
- ActiveSessionRole,
- ProjectsPathRole,
- ProjectsDisplayRole,
- ShortcutRole
- };
-
- explicit SessionModel(QObject *parent = nullptr);
-
- int indexOfSession(const QString &session);
- QString sessionAt(int row) const;
-
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
-
- QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
- QVariant data(const QModelIndex &index, int role) const override;
- QHash<int, QByteArray> roleNames() const override;
- void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
-
- Q_SCRIPTABLE bool isDefaultVirgin() const;
-
-signals:
- void sessionSwitched();
- void sessionCreated(const QString &sessionName);
-
-public slots:
- void resetSessions();
- void newSession(QWidget *parent);
- void cloneSession(QWidget *parent, const QString &session);
- void deleteSessions(const QStringList &sessions);
- void renameSession(QWidget *parent, const QString &session);
- void switchToSession(const QString &session);
-
-private:
- void runSessionNameInputDialog(ProjectExplorer::Internal::SessionNameInputDialog *sessionInputDialog, std::function<void(const QString &)> createSession);
-
- QStringList m_sortedSessions;
- int m_currentSortColumn = 0;
- Qt::SortOrder m_currentSortOrder = Qt::AscendingOrder;
-};
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/sessionview.cpp b/src/plugins/projectexplorer/sessionview.cpp
deleted file mode 100644
index e4b3b1a5d0..0000000000
--- a/src/plugins/projectexplorer/sessionview.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "sessionview.h"
-
-#include "session.h"
-
-#include <utils/algorithm.h>
-
-#include <QHeaderView>
-#include <QItemSelection>
-#include <QStringList>
-#include <QStyledItemDelegate>
-
-namespace ProjectExplorer {
-namespace Internal {
-
-// custom item delegate class
-class RemoveItemFocusDelegate : public QStyledItemDelegate
-{
-public:
- RemoveItemFocusDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {
- }
-
-protected:
- void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
-};
-
-void RemoveItemFocusDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
-{
- QStyleOptionViewItem opt = option;
- opt.state &= ~QStyle::State_HasFocus;
- QStyledItemDelegate::paint(painter, opt, index);
-}
-
-SessionView::SessionView(QWidget *parent)
- : Utils::TreeView(parent)
-{
- setItemDelegate(new RemoveItemFocusDelegate(this));
- setSelectionBehavior(QAbstractItemView::SelectRows);
- setSelectionMode(QAbstractItemView::ExtendedSelection);
- setWordWrap(false);
- setRootIsDecorated(false);
- setSortingEnabled(true);
-
- setModel(&m_sessionModel);
- sortByColumn(0, Qt::AscendingOrder);
-
- // Ensure that the full session name is visible.
- header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
-
- QItemSelection firstRow(m_sessionModel.index(0,0), m_sessionModel.index(
- 0, m_sessionModel.columnCount() - 1));
- selectionModel()->select(firstRow, QItemSelectionModel::QItemSelectionModel::
- SelectCurrent);
-
- connect(this, &Utils::TreeView::activated, [this](const QModelIndex &index){
- emit sessionActivated(m_sessionModel.sessionAt(index.row()));
- });
- connect(selectionModel(), &QItemSelectionModel::selectionChanged, [this] {
- emit sessionsSelected(selectedSessions());
- });
-
- connect(&m_sessionModel, &SessionModel::sessionSwitched,
- this, &SessionView::sessionSwitched);
- connect(&m_sessionModel, &SessionModel::modelReset,
- this, &SessionView::selectActiveSession);
- connect(&m_sessionModel, &SessionModel::sessionCreated,
- this, &SessionView::selectSession);
- }
-
-void SessionView::createNewSession()
-{
- m_sessionModel.newSession(this);
-}
-
-void SessionView::deleteSelectedSessions()
-{
- deleteSessions(selectedSessions());
-}
-
-void SessionView::deleteSessions(const QStringList &sessions)
-{
- m_sessionModel.deleteSessions(sessions);
-}
-
-void SessionView::cloneCurrentSession()
-{
- m_sessionModel.cloneSession(this, currentSession());
-}
-
-void SessionView::renameCurrentSession()
-{
- m_sessionModel.renameSession(this, currentSession());
-}
-
-void SessionView::switchToCurrentSession()
-{
- m_sessionModel.switchToSession(currentSession());
-}
-
-QString SessionView::currentSession()
-{
- return m_sessionModel.sessionAt(selectionModel()->currentIndex().row());
-}
-
-SessionModel *SessionView::sessionModel()
-{
- return &m_sessionModel;
-}
-
-void SessionView::selectActiveSession()
-{
- selectSession(SessionManager::activeSession());
-}
-
-void SessionView::selectSession(const QString &sessionName)
-{
- int row = m_sessionModel.indexOfSession(sessionName);
- selectionModel()->setCurrentIndex(model()->index(row, 0),
- QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
-}
-
-void SessionView::showEvent(QShowEvent *event)
-{
- Utils::TreeView::showEvent(event);
- selectActiveSession();
- setFocus();
-}
-
-void SessionView::keyPressEvent(QKeyEvent *event)
-{
- if (event->key() != Qt::Key_Delete && event->key() != Qt::Key_Backspace) {
- TreeView::keyPressEvent(event);
- return;
- }
- const QStringList sessions = selectedSessions();
- if (!sessions.contains("default") && !Utils::anyOf(sessions,
- [](const QString &session) { return session == SessionManager::activeSession(); })) {
- deleteSessions(sessions);
- }
-}
-
-QStringList SessionView::selectedSessions() const
-{
- return Utils::transform(selectionModel()->selectedRows(), [this](const QModelIndex &index) {
- return m_sessionModel.sessionAt(index.row());
- });
-}
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/sessionview.h b/src/plugins/projectexplorer/sessionview.h
deleted file mode 100644
index 656da080ea..0000000000
--- a/src/plugins/projectexplorer/sessionview.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include "sessionmodel.h"
-
-#include <utils/itemviews.h>
-
-#include <QAbstractTableModel>
-
-namespace ProjectExplorer::Internal {
-
-class SessionView : public Utils::TreeView
-{
- Q_OBJECT
-
-public:
- explicit SessionView(QWidget *parent = nullptr);
-
- void createNewSession();
- void deleteSelectedSessions();
- void cloneCurrentSession();
- void renameCurrentSession();
- void switchToCurrentSession();
-
- QString currentSession();
- SessionModel* sessionModel();
- void selectActiveSession();
- void selectSession(const QString &sessionName);
-
-signals:
- void sessionActivated(const QString &session);
- void sessionsSelected(const QStringList &sessions);
- void sessionSwitched();
-
-private:
- void showEvent(QShowEvent* event) override;
- void keyPressEvent(QKeyEvent *event) override;
-
- void deleteSessions(const QStringList &sessions);
- QStringList selectedSessions() const;
-
- SessionModel m_sessionModel;
-};
-
-} // ProjectExplorer::Internal
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index 8f227512ee..d2e59aab06 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -21,8 +21,8 @@
#include "projectexplorericons.h"
#include "projectexplorersettings.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "runconfiguration.h"
-#include "session.h"
#include <coreplugin/coreconstants.h>
@@ -120,10 +120,10 @@ Target::Target(Project *project, Kit *k, _constructor_tag) :
});
connect(this, &Target::parsingFinished, this, [this, project](bool success) {
- if (success && this == SessionManager::startupTarget())
+ if (success && this == ProjectManager::startupTarget())
updateDefaultRunConfigurations();
// For testing.
- emit SessionManager::instance()->projectFinishedParsing(project);
+ emit ProjectManager::instance()->projectFinishedParsing(project);
emit project->anyParsingFinished(this, success);
}, Qt::QueuedConnection); // Must wait for run configs to change their enabled state.
@@ -242,6 +242,70 @@ QString Target::activeBuildKey() const
return d->m_activeRunConfiguration->buildKey();
}
+void Target::setActiveBuildConfiguration(BuildConfiguration *bc, SetActive cascade)
+{
+ QTC_ASSERT(project(), return);
+
+ if (project()->isShuttingDown() || isShuttingDown())
+ return;
+
+ setActiveBuildConfiguration(bc);
+
+ if (!bc)
+ return;
+ if (cascade != SetActive::Cascade || !ProjectManager::isProjectConfigurationCascading())
+ return;
+
+ Id kitId = kit()->id();
+ QString name = bc->displayName(); // We match on displayname
+ for (Project *otherProject : ProjectManager::projects()) {
+ if (otherProject == project())
+ continue;
+ Target *otherTarget = otherProject->activeTarget();
+ if (!otherTarget || otherTarget->kit()->id() != kitId)
+ continue;
+
+ for (BuildConfiguration *otherBc : otherTarget->buildConfigurations()) {
+ if (otherBc->displayName() == name) {
+ otherTarget->setActiveBuildConfiguration(otherBc);
+ break;
+ }
+ }
+ }
+}
+
+void Target::setActiveDeployConfiguration(DeployConfiguration *dc, SetActive cascade)
+{
+ QTC_ASSERT(project(), return);
+
+ if (project()->isShuttingDown() || isShuttingDown())
+ return;
+
+ setActiveDeployConfiguration(dc);
+
+ if (!dc)
+ return;
+ if (cascade != SetActive::Cascade || !ProjectManager::isProjectConfigurationCascading())
+ return;
+
+ Id kitId = kit()->id();
+ QString name = dc->displayName(); // We match on displayname
+ for (Project *otherProject : ProjectManager::projects()) {
+ if (otherProject == project())
+ continue;
+ Target *otherTarget = otherProject->activeTarget();
+ if (!otherTarget || otherTarget->kit()->id() != kitId)
+ continue;
+
+ for (DeployConfiguration *otherDc : otherTarget->deployConfigurations()) {
+ if (otherDc->displayName() == name) {
+ otherTarget->setActiveDeployConfiguration(otherDc);
+ break;
+ }
+ }
+ }
+}
+
Utils::Id Target::id() const
{
return d->m_kit->id();
@@ -307,9 +371,9 @@ bool Target::removeBuildConfiguration(BuildConfiguration *bc)
if (activeBuildConfiguration() == bc) {
if (d->m_buildConfigurations.isEmpty())
- SessionManager::setActiveBuildConfiguration(this, nullptr, SetActive::Cascade);
+ setActiveBuildConfiguration(nullptr, SetActive::Cascade);
else
- SessionManager::setActiveBuildConfiguration(this, d->m_buildConfigurations.at(0), SetActive::Cascade);
+ setActiveBuildConfiguration(d->m_buildConfigurations.at(0), SetActive::Cascade);
}
emit removedBuildConfiguration(bc);
@@ -377,10 +441,9 @@ bool Target::removeDeployConfiguration(DeployConfiguration *dc)
if (activeDeployConfiguration() == dc) {
if (d->m_deployConfigurations.isEmpty())
- SessionManager::setActiveDeployConfiguration(this, nullptr, SetActive::Cascade);
+ setActiveDeployConfiguration(nullptr, SetActive::Cascade);
else
- SessionManager::setActiveDeployConfiguration(this, d->m_deployConfigurations.at(0),
- SetActive::Cascade);
+ setActiveDeployConfiguration(d->m_deployConfigurations.at(0), SetActive::Cascade);
}
ProjectExplorerPlugin::targetSelector()->removedDeployConfiguration(dc);
diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h
index 78f0b5f3b5..aeca2fd9e0 100644
--- a/src/plugins/projectexplorer/target.h
+++ b/src/plugins/projectexplorer/target.h
@@ -26,11 +26,13 @@ class Project;
class ProjectConfigurationModel;
class RunConfiguration;
+enum class SetActive : int { Cascade, NoCascade };
+
class TargetPrivate;
class PROJECTEXPLORER_EXPORT Target : public QObject
{
- friend class SessionManager; // for setActiveBuild and setActiveDeployConfiguration
+ friend class ProjectManager; // for setActiveBuild and setActiveDeployConfiguration
Q_OBJECT
public:
@@ -109,6 +111,9 @@ public:
QString activeBuildKey() const; // Build key of active run configuaration
+ void setActiveBuildConfiguration(BuildConfiguration *bc, SetActive cascade);
+ void setActiveDeployConfiguration(DeployConfiguration *dc, SetActive cascade);
+
signals:
void targetEnabled(bool);
void iconChanged();
diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp
index 6d8c81e634..d2fdc3b43a 100644
--- a/src/plugins/projectexplorer/targetsettingspanel.cpp
+++ b/src/plugins/projectexplorer/targetsettingspanel.cpp
@@ -12,9 +12,9 @@
#include "project.h"
#include "projectexplorericons.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projectwindow.h"
#include "runsettingspropertiespage.h"
-#include "session.h"
#include "target.h"
#include "targetsetuppage.h"
#include "task.h"
@@ -281,7 +281,7 @@ public:
QFont font = parent()->data(column, role).value<QFont>();
if (TargetItem *targetItem = parent()->currentTargetItem()) {
Target *t = targetItem->target();
- if (t && t->id() == m_kitId && m_project == SessionManager::startupProject())
+ if (t && t->id() == m_kitId && m_project == ProjectManager::startupProject())
font.setBold(true);
}
return font;
@@ -334,7 +334,7 @@ public:
// Go to Run page, when on Run previously etc.
TargetItem *previousItem = parent()->currentTargetItem();
m_currentChild = previousItem ? previousItem->m_currentChild : DefaultPage;
- SessionManager::setActiveTarget(m_project, target(), SetActive::Cascade);
+ m_project->setActiveTarget(target(), SetActive::Cascade);
parent()->setData(column, QVariant::fromValue(static_cast<TreeItem *>(this)),
ItemActivatedFromBelowRole);
}
@@ -346,7 +346,7 @@ public:
int child = indexOf(data.value<TreeItem *>());
QTC_ASSERT(child != -1, return false);
m_currentChild = child; // Triggered from sub-item.
- SessionManager::setActiveTarget(m_project, target(), SetActive::Cascade);
+ m_project->setActiveTarget(target(), SetActive::Cascade);
// Propagate Build/Run selection up.
parent()->setData(column, QVariant::fromValue(static_cast<TreeItem *>(this)),
ItemActivatedFromBelowRole);
@@ -355,7 +355,7 @@ public:
if (role == ItemActivatedFromAboveRole) {
// Usually programmatic activation, e.g. after opening the Project mode.
- SessionManager::setActiveTarget(m_project, target(), SetActive::Cascade);
+ m_project->setActiveTarget(target(), SetActive::Cascade);
return true;
}
return false;
@@ -377,7 +377,7 @@ public:
= menu->addAction(Tr::tr("Enable Kit for All Projects"));
enableForAllAction->setEnabled(isSelectable);
QObject::connect(enableForAllAction, &QAction::triggered, [kit] {
- for (Project * const p : SessionManager::projects()) {
+ for (Project * const p : ProjectManager::projects()) {
if (!p->target(kit))
p->addTargetForKit(kit);
}
@@ -411,7 +411,7 @@ public:
QAction *disableForAllAction = menu->addAction(Tr::tr("Disable Kit for All Projects"));
disableForAllAction->setEnabled(isSelectable);
QObject::connect(disableForAllAction, &QAction::triggered, [kit] {
- for (Project * const p : SessionManager::projects()) {
+ for (Project * const p : ProjectManager::projects()) {
Target * const t = p->target(kit);
if (!t)
continue;
diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp
index a17aa58c94..fd1e8a78c6 100644
--- a/src/plugins/projectexplorer/targetsetuppage.cpp
+++ b/src/plugins/projectexplorer/targetsetuppage.cpp
@@ -11,18 +11,17 @@
#include "project.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
-#include "session.h"
#include "target.h"
#include "targetsetupwidget.h"
#include "task.h"
#include <coreplugin/icore.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-#include <utils/wizard.h>
#include <utils/algorithm.h>
#include <utils/fancylineedit.h>
+#include <utils/process.h>
+#include <utils/qtcassert.h>
+#include <utils/wizard.h>
#include <QApplication>
#include <QCheckBox>
@@ -658,7 +657,7 @@ bool TargetSetupPage::setupProject(Project *project)
if (m_importer)
activeTarget = m_importer->preferredTarget(project->targets());
if (activeTarget)
- SessionManager::setActiveTarget(project, activeTarget, SetActive::NoCascade);
+ project->setActiveTarget(activeTarget, SetActive::NoCascade);
return true;
}
diff --git a/src/plugins/projectexplorer/targetsetupwidget.cpp b/src/plugins/projectexplorer/targetsetupwidget.cpp
index cae28fc3e1..63b61401d5 100644
--- a/src/plugins/projectexplorer/targetsetupwidget.cpp
+++ b/src/plugins/projectexplorer/targetsetupwidget.cpp
@@ -180,10 +180,8 @@ void TargetSetupWidget::manageKit()
if (!m_kit)
return;
- if (auto kitPage = KitOptionsPage::instance()) {
- kitPage->showKit(m_kit);
- Core::ICore::showOptionsDialog(Constants::KITS_SETTINGS_PAGE_ID, parentWidget());
- }
+ KitOptionsPage::showKit(m_kit);
+ Core::ICore::showOptionsDialog(Constants::KITS_SETTINGS_PAGE_ID, parentWidget());
}
void TargetSetupWidget::setProjectPath(const FilePath &projectPath)
diff --git a/src/plugins/projectexplorer/task.cpp b/src/plugins/projectexplorer/task.cpp
index dab4c7ed17..03c2a282be 100644
--- a/src/plugins/projectexplorer/task.cpp
+++ b/src/plugins/projectexplorer/task.cpp
@@ -8,8 +8,8 @@
#include "projectexplorertr.h"
#include <app/app_version.h>
+#include <texteditor/fontsettings.h>
#include <texteditor/textmark.h>
-
#include <utils/algorithm.h>
#include <utils/utilsicons.h>
#include <utils/qtcassert.h>
@@ -105,11 +105,16 @@ void Task::setFile(const Utils::FilePath &file_)
}
}
-QString Task::description() const
+QString Task::description(DescriptionTags tags) const
{
- QString desc = summary;
- if (!details.isEmpty())
- desc.append('\n').append(details.join('\n'));
+ QString desc;
+ if (tags & WithSummary)
+ desc = summary;
+ if (!details.isEmpty()) {
+ if (!desc.isEmpty())
+ desc.append('\n');
+ desc.append(details.join('\n'));
+ }
return desc;
}
@@ -120,6 +125,39 @@ QIcon Task::icon() const
return m_icon;
}
+QString Task::formattedDescription(DescriptionTags tags, const QString &extraHeading) const
+{
+ if (isNull())
+ return {};
+
+ QString text = description(tags);
+ const int offset = (tags & WithSummary) ? 0 : summary.size() + 1;
+ static const QString linkTagStartPlaceholder("__QTC_LINK_TAG_START__");
+ static const QString linkTagEndPlaceholder("__QTC_LINK_TAG_END__");
+ static const QString linkEndPlaceholder("__QTC_LINK_END__");
+ if (tags & WithLinks) {
+ for (auto formatRange = formats.crbegin(); formatRange != formats.crend(); ++formatRange) {
+ if (!formatRange->format.isAnchor())
+ continue;
+ text.insert(formatRange->start - offset + formatRange->length, linkEndPlaceholder);
+ text.insert(formatRange->start - offset, QString::fromLatin1("%1%2%3").arg(
+ linkTagStartPlaceholder, formatRange->format.anchorHref(), linkTagEndPlaceholder));
+ }
+ }
+ text = text.toHtmlEscaped();
+ if (tags & WithLinks) {
+ text.replace(linkEndPlaceholder, "</a>");
+ text.replace(linkTagStartPlaceholder, "<a href=\"");
+ text.replace(linkTagEndPlaceholder, "\">");
+ }
+ const QString htmlExtraHeading = extraHeading.isEmpty()
+ ? QString()
+ : QString::fromUtf8("<b>%1</b><br/>").arg(extraHeading);
+ return QString::fromUtf8("<html><body>%1<code style=\"white-space:pre;font-family:%2\">"
+ "%3</code></body></html>")
+ .arg(htmlExtraHeading, TextEditor::FontSettings::defaultFixedFontFamily(), text);
+}
+
//
// functions
//
diff --git a/src/plugins/projectexplorer/task.h b/src/plugins/projectexplorer/task.h
index f38302f90f..830cea7939 100644
--- a/src/plugins/projectexplorer/task.h
+++ b/src/plugins/projectexplorer/task.h
@@ -38,6 +38,9 @@ public:
};
using Options = char;
+ enum DescriptionTag { WithSummary = 1, WithLinks = 2 };
+ using DescriptionTags = QFlags<DescriptionTag>;
+
Task() = default;
Task(TaskType type, const QString &description,
const Utils::FilePath &file, int line, Utils::Id category,
@@ -49,8 +52,9 @@ public:
bool isNull() const;
void clear();
void setFile(const Utils::FilePath &file);
- QString description() const;
+ QString description(DescriptionTags tags = WithSummary) const;
QIcon icon() const;
+ QString formattedDescription(DescriptionTags tags, const QString &extraHeading = {}) const;
friend PROJECTEXPLORER_EXPORT bool operator==(const Task &t1, const Task &t2);
friend PROJECTEXPLORER_EXPORT bool operator<(const Task &a, const Task &b);
diff --git a/src/plugins/projectexplorer/taskfile.cpp b/src/plugins/projectexplorer/taskfile.cpp
index 6375d12ee7..c967521d89 100644
--- a/src/plugins/projectexplorer/taskfile.cpp
+++ b/src/plugins/projectexplorer/taskfile.cpp
@@ -6,20 +6,22 @@
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
-#include "session.h"
#include "taskhub.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
+#include <coreplugin/messagemanager.h>
+#include <coreplugin/session.h>
#include <utils/algorithm.h>
#include <utils/filepath.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <QAction>
#include <QMessageBox>
+using namespace Core;
using namespace Utils;
namespace ProjectExplorer {
@@ -147,6 +149,10 @@ static bool parseTaskFile(QString *errorString, const FilePath &name)
}
description = unescape(description);
+ if (description.trimmed().isEmpty()) {
+ MessageManager::writeFlashing(Tr::tr("Ignoring invalid task (no text)."));
+ continue;
+ }
TaskHub::addTask(Task(type, description, FilePath::fromUserInput(file), line,
Constants::TASK_CATEGORY_TASKLIST_ID));
}
diff --git a/src/plugins/projectexplorer/taskhub.cpp b/src/plugins/projectexplorer/taskhub.cpp
index da839e89f1..58e797de80 100644
--- a/src/plugins/projectexplorer/taskhub.cpp
+++ b/src/plugins/projectexplorer/taskhub.cpp
@@ -51,13 +51,9 @@ public:
: Tr::tr("Warning"));
setPriority(task.type == Task::Error ? TextEditor::TextMark::NormalPriority
: TextEditor::TextMark::LowPriority);
- if (task.category == Constants::TASK_CATEGORY_COMPILE) {
- setToolTip("<html><body><b>" + Tr::tr("Build Issue")
- + "</b><br/><code style=\"white-space:pre;font-family:monospace\">"
- + task.description().toHtmlEscaped() + "</code></body></html>");
- } else {
- setToolTip(task.description());
- }
+ setToolTip(task.formattedDescription({Task::WithSummary | Task::WithLinks},
+ task.category == Constants::TASK_CATEGORY_COMPILE
+ ? Tr::tr("Build Issue") : QString()));
setIcon(task.icon());
setVisible(!task.icon().isNull());
}
diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp
index b8f7d72306..11591e707d 100644
--- a/src/plugins/projectexplorer/taskmodel.cpp
+++ b/src/plugins/projectexplorer/taskmodel.cpp
@@ -210,58 +210,82 @@ void TaskModel::clearTasks(Utils::Id categoryId)
QModelIndex TaskModel::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid())
- return QModelIndex();
+ return createIndex(row, column, quintptr(parent.row() + 1));
return createIndex(row, column);
}
QModelIndex TaskModel::parent(const QModelIndex &child) const
{
- Q_UNUSED(child)
- return QModelIndex();
+ if (child.internalId())
+ return index(child.internalId() - 1, 0);
+ return {};
}
int TaskModel::rowCount(const QModelIndex &parent) const
{
- return parent.isValid() ? 0 : m_tasks.count();
+ if (!parent.isValid())
+ return m_tasks.count();
+ if (parent.column() != 0)
+ return 0;
+ return task(parent).details.isEmpty() ? 0 : 1;
}
int TaskModel::columnCount(const QModelIndex &parent) const
{
- return parent.isValid() ? 0 : 1;
+ return parent.isValid() ? 1 : 2;
}
QVariant TaskModel::data(const QModelIndex &index, int role) const
{
- int row = index.row();
- if (!index.isValid() || row < 0 || row >= m_tasks.count() || index.column() != 0)
- return QVariant();
-
- if (role == TaskModel::File)
- return m_tasks.at(index.row()).file.toString();
- else if (role == TaskModel::Line)
- return m_tasks.at(index.row()).line;
- else if (role == TaskModel::MovedLine)
- return m_tasks.at(index.row()).movedLine;
- else if (role == TaskModel::Description)
- return m_tasks.at(index.row()).description();
- else if (role == TaskModel::FileNotFound)
- return m_fileNotFound.value(m_tasks.at(index.row()).file.toString());
- else if (role == TaskModel::Type)
- return (int)m_tasks.at(index.row()).type;
- else if (role == TaskModel::Category)
- return m_tasks.at(index.row()).category.uniqueIdentifier();
- else if (role == TaskModel::Icon)
- return m_tasks.at(index.row()).icon();
- else if (role == TaskModel::Task_t)
- return QVariant::fromValue(task(index));
- return QVariant();
+ if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index.parent())
+ || index.column() >= columnCount(index.parent())) {
+ return {};
+ }
+
+ if (index.internalId()) {
+ const Task &task = m_tasks.at(index.internalId() - 1);
+ if (role != Qt::DisplayRole)
+ return {};
+ return task.formattedDescription(Task::WithLinks);
+ }
+
+ static const auto lineString = [](const Task &task) {
+ QString file = task.file.fileName();
+ const int line = task.movedLine > 0 ? task.movedLine : task.line;
+ if (line > 0)
+ file.append(':').append(QString::number(line));
+ return file;
+ };
+
+ const Task &task = m_tasks.at(index.row());
+ if (index.column() == 1) {
+ if (role == Qt::DisplayRole)
+ return lineString(task);
+ if (role == Qt::ToolTipRole)
+ return task.file.toUserOutput();
+ return {};
+ }
+
+ switch (role) {
+ case Qt::DecorationRole:
+ return task.icon();
+ case Qt::DisplayRole:
+ return task.summary;
+ case TaskModel::Description:
+ return task.description();
+ case TaskModel::Type:
+ return int(task.type);
+ }
+ return {};
}
Task TaskModel::task(const QModelIndex &index) const
{
int row = index.row();
- if (!index.isValid() || row < 0 || row >= m_tasks.count())
+ if (!index.isValid() || row < 0 || row >= m_tasks.count() || index.internalId()
+ || index.column() > 0) {
return Task();
+ }
return m_tasks.at(row);
}
@@ -387,7 +411,8 @@ void TaskFilterModel::updateFilterProperties(
bool TaskFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
- Q_UNUSED(source_parent)
+ if (source_parent.isValid())
+ return true;
return filterAcceptsTask(taskModel()->tasks().at(source_row));
}
diff --git a/src/plugins/projectexplorer/taskmodel.h b/src/plugins/projectexplorer/taskmodel.h
index e10833f613..5fa37c02d1 100644
--- a/src/plugins/projectexplorer/taskmodel.h
+++ b/src/plugins/projectexplorer/taskmodel.h
@@ -44,7 +44,7 @@ public:
int sizeOfLineNumber(const QFont &font);
void setFileNotFound(const QModelIndex &index, bool b);
- enum Roles { File = Qt::UserRole, Line, MovedLine, Description, FileNotFound, Type, Category, Icon, Task_t };
+ enum Roles { Description = Qt::UserRole, Type};
int taskCount(Utils::Id categoryId);
int errorTaskCount(Utils::Id categoryId);
diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp
index 52e3899d65..9ae93c0bbf 100644
--- a/src/plugins/projectexplorer/taskwindow.cpp
+++ b/src/plugins/projectexplorer/taskwindow.cpp
@@ -6,7 +6,6 @@
#include "itaskhandler.h"
#include "projectexplorericons.h"
#include "projectexplorertr.h"
-#include "session.h"
#include "task.h"
#include "taskhub.h"
#include "taskmodel.h"
@@ -17,32 +16,38 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/itemviewfind.h>
-#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/session.h>
#include <utils/algorithm.h>
#include <utils/fileinprojectfinder.h>
+#include <utils/hostosinfo.h>
#include <utils/itemviews.h>
#include <utils/outputformatter.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
#include <utils/theme/theme.h>
+#include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h>
+#include <QAbstractTextDocumentLayout>
+#include <QApplication>
#include <QDir>
+#include <QLabel>
+#include <QMenu>
#include <QPainter>
+#include <QScrollBar>
#include <QStyledItemDelegate>
-#include <QMenu>
+#include <QTextDocument>
#include <QToolButton>
-#include <QScrollBar>
+#include <QVBoxLayout>
+using namespace Core;
using namespace Utils;
-namespace {
-const int ELLIPSIS_GRADIENT_WIDTH = 16;
const char SESSION_FILTER_CATEGORIES[] = "TaskWindow.Categories";
const char SESSION_FILTER_WARNINGS[] = "TaskWindow.IncludeWarnings";
-}
namespace ProjectExplorer {
@@ -84,195 +89,42 @@ bool ITaskHandler::canHandle(const Tasks &tasks) const
namespace Internal {
-class TaskView : public ListView
+class TaskView : public TreeView
{
public:
- TaskView(QWidget *parent = nullptr);
- ~TaskView() override;
+ TaskView();
+ void resizeColumns();
private:
void resizeEvent(QResizeEvent *e) override;
+ void keyReleaseEvent(QKeyEvent *e) override;
+ bool event(QEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
- void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
+ void mouseReleaseEvent(QMouseEvent *e) override;
- Link locationForPos(const QPoint &pos);
+ QString anchorAt(const QPoint &pos);
+ void showToolTip(const Task &task, const QPoint &pos);
- bool m_linksActive = true;
- Qt::MouseButton m_mouseButtonPressed = Qt::NoButton;
+ QString m_hoverAnchor;
+ QString m_clickAnchor;
};
class TaskDelegate : public QStyledItemDelegate
{
- Q_OBJECT
-
- friend class TaskView; // for using Positions::minimumSize()
-
public:
- TaskDelegate(QObject * parent = nullptr);
- ~TaskDelegate() override;
- void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
- QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
-
- // TaskView uses this method if the size of the taskview changes
- void emitSizeHintChanged(const QModelIndex &index);
-
- void currentChanged(const QModelIndex &current, const QModelIndex &previous);
-
- QString hrefForPos(const QPointF &pos);
+ using QStyledItemDelegate::QStyledItemDelegate;
+ QTextDocument &doc() { return m_doc; }
private:
- void generateGradientPixmap(int width, int height, QColor color, bool selected) const;
-
- mutable int m_cachedHeight = 0;
- mutable QFont m_cachedFont;
- mutable QList<QPair<QRectF, QString>> m_hrefs;
-
- /*
- Collapsed:
- +----------------------------------------------------------------------------------------------------+
- | TASKICONAREA TEXTAREA FILEAREA LINEAREA |
- +----------------------------------------------------------------------------------------------------+
-
- Expanded:
- +----------------------------------------------------------------------------------------------------+
- | TASKICONICON TEXTAREA FILEAREA LINEAREA |
- | more text -------------------------------------------------------------------------> |
- +----------------------------------------------------------------------------------------------------+
- */
- class Positions
- {
- public:
- Positions(const QStyleOptionViewItem &options, TaskModel *model) :
- m_totalWidth(options.rect.width()),
- m_maxFileLength(model->sizeOfFile(options.font)),
- m_maxLineLength(model->sizeOfLineNumber(options.font)),
- m_realFileLength(m_maxFileLength),
- m_top(options.rect.top()),
- m_bottom(options.rect.bottom())
- {
- int flexibleArea = lineAreaLeft() - textAreaLeft() - ITEM_SPACING;
- if (m_maxFileLength > flexibleArea / 2)
- m_realFileLength = flexibleArea / 2;
- m_fontHeight = QFontMetrics(options.font).height();
- }
-
- int top() const { return m_top + ITEM_MARGIN; }
- int left() const { return ITEM_MARGIN; }
- int right() const { return m_totalWidth - ITEM_MARGIN; }
- int bottom() const { return m_bottom; }
- int firstLineHeight() const { return m_fontHeight + 1; }
- static int minimumHeight() { return taskIconHeight() + 2 * ITEM_MARGIN; }
-
- int taskIconLeft() const { return left(); }
- static int taskIconWidth() { return TASK_ICON_SIZE; }
- static int taskIconHeight() { return TASK_ICON_SIZE; }
- int taskIconRight() const { return taskIconLeft() + taskIconWidth(); }
- QRect taskIcon() const { return QRect(taskIconLeft(), top(), taskIconWidth(), taskIconHeight()); }
-
- int textAreaLeft() const { return taskIconRight() + ITEM_SPACING; }
- int textAreaWidth() const { return textAreaRight() - textAreaLeft(); }
- int textAreaRight() const { return fileAreaLeft() - ITEM_SPACING; }
- QRect textArea() const { return QRect(textAreaLeft(), top(), textAreaWidth(), firstLineHeight()); }
-
- int fileAreaLeft() const { return fileAreaRight() - fileAreaWidth(); }
- int fileAreaWidth() const { return m_realFileLength; }
- int fileAreaRight() const { return lineAreaLeft() - ITEM_SPACING; }
- QRect fileArea() const { return QRect(fileAreaLeft(), top(), fileAreaWidth(), firstLineHeight()); }
-
- int lineAreaLeft() const { return lineAreaRight() - lineAreaWidth(); }
- int lineAreaWidth() const { return m_maxLineLength; }
- int lineAreaRight() const { return right(); }
- QRect lineArea() const { return QRect(lineAreaLeft(), top(), lineAreaWidth(), firstLineHeight()); }
-
- private:
- int m_totalWidth;
- int m_maxFileLength;
- int m_maxLineLength;
- int m_realFileLength;
- int m_top;
- int m_bottom;
- int m_fontHeight;
-
- static const int TASK_ICON_SIZE = 16;
- static const int ITEM_MARGIN = 2;
- static const int ITEM_SPACING = 2 * ITEM_MARGIN;
- };
-};
-
-TaskView::TaskView(QWidget *parent)
- : ListView(parent)
-{
- setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
- setMouseTracking(true);
- setAutoScroll(false); // QTCREATORBUG-25101
-
- QFontMetrics fm(font());
- int vStepSize = fm.height() + 3;
- if (vStepSize < TaskDelegate::Positions::minimumHeight())
- vStepSize = TaskDelegate::Positions::minimumHeight();
-
- verticalScrollBar()->setSingleStep(vStepSize);
-}
-
-TaskView::~TaskView() = default;
-
-void TaskView::resizeEvent(QResizeEvent *e)
-{
- Q_UNUSED(e)
- static_cast<TaskDelegate *>(itemDelegate())->emitSizeHintChanged(selectionModel()->currentIndex());
-}
-
-void TaskView::mousePressEvent(QMouseEvent *e)
-{
- m_mouseButtonPressed = e->button();
- ListView::mousePressEvent(e);
-}
-
-void TaskView::mouseReleaseEvent(QMouseEvent *e)
-{
- if (m_linksActive && m_mouseButtonPressed == Qt::LeftButton) {
- const Link loc = locationForPos(e->pos());
- if (!loc.targetFilePath.isEmpty()) {
- Core::EditorManager::openEditorAt(loc, {},
- Core::EditorManager::SwitchSplitIfAlreadyVisible);
- }
- }
-
- // Mouse was released, activate links again
- m_linksActive = true;
- m_mouseButtonPressed = Qt::NoButton;
- ListView::mouseReleaseEvent(e);
-}
-
-void TaskView::mouseMoveEvent(QMouseEvent *e)
-{
- // Cursor was dragged, deactivate links
- if (m_mouseButtonPressed != Qt::NoButton)
- m_linksActive = false;
-
- viewport()->setCursor(m_linksActive && !locationForPos(e->pos()).targetFilePath.isEmpty()
- ? Qt::PointingHandCursor : Qt::ArrowCursor);
- ListView::mouseMoveEvent(e);
-}
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
-Link TaskView::locationForPos(const QPoint &pos)
-{
- const auto delegate = qobject_cast<TaskDelegate *>(itemDelegate(indexAt(pos)));
- if (!delegate)
- return {};
- OutputFormatter formatter;
- Link loc;
- connect(&formatter, &OutputFormatter::openInEditorRequested, this, [&loc](const Link &link) {
- loc = link;
- });
+ bool needsSpecialHandling(const QModelIndex &index) const;
- const QString href = delegate->hrefForPos(pos);
- if (!href.isEmpty())
- formatter.handleLink(href);
- return loc;
-}
+ mutable QTextDocument m_doc;
+};
/////
// TaskWindow
@@ -289,9 +141,8 @@ public:
Internal::TaskModel *m_model;
Internal::TaskFilterModel *m_filter;
- Internal::TaskView *m_listview;
+ TaskView m_treeView;
Core::IContext *m_taskWindowContext;
- QMenu *m_contextMenu;
QMap<const QAction *, ITaskHandler *> m_actionToHandlerMap;
ITaskHandler *m_defaultHandler = nullptr;
QToolButton *m_filterWarningsButton;
@@ -318,45 +169,45 @@ TaskWindow::TaskWindow() : d(std::make_unique<TaskWindowPrivate>())
{
d->m_model = new Internal::TaskModel(this);
d->m_filter = new Internal::TaskFilterModel(d->m_model);
- d->m_listview = new Internal::TaskView;
+ d->m_filter->setAutoAcceptChildRows(true);
auto agg = new Aggregation::Aggregate;
- agg->add(d->m_listview);
- agg->add(new Core::ItemViewFind(d->m_listview, TaskModel::Description));
-
- d->m_listview->setModel(d->m_filter);
- d->m_listview->setFrameStyle(QFrame::NoFrame);
- d->m_listview->setWindowTitle(displayName());
- d->m_listview->setSelectionMode(QAbstractItemView::ExtendedSelection);
- auto *tld = new Internal::TaskDelegate(this);
- d->m_listview->setItemDelegate(tld);
- d->m_listview->setWindowIcon(Icons::WINDOW.icon());
- d->m_listview->setContextMenuPolicy(Qt::ActionsContextMenu);
- d->m_listview->setAttribute(Qt::WA_MacShowFocusRect, false);
-
- d->m_taskWindowContext = new Core::IContext(d->m_listview);
- d->m_taskWindowContext->setWidget(d->m_listview);
+ agg->add(&d->m_treeView);
+ agg->add(new Core::ItemViewFind(&d->m_treeView, TaskModel::Description));
+
+ d->m_treeView.setHeaderHidden(true);
+ d->m_treeView.setExpandsOnDoubleClick(false);
+ d->m_treeView.setAlternatingRowColors(true);
+ d->m_treeView.setTextElideMode(Qt::ElideMiddle);
+ d->m_treeView.setItemDelegate(new TaskDelegate(this));
+ d->m_treeView.setModel(d->m_filter);
+ d->m_treeView.setFrameStyle(QFrame::NoFrame);
+ d->m_treeView.setWindowTitle(displayName());
+ d->m_treeView.setSelectionMode(QAbstractItemView::ExtendedSelection);
+ d->m_treeView.setWindowIcon(Icons::WINDOW.icon());
+ d->m_treeView.setContextMenuPolicy(Qt::ActionsContextMenu);
+ d->m_treeView.setAttribute(Qt::WA_MacShowFocusRect, false);
+ d->m_treeView.resizeColumns();
+
+ d->m_taskWindowContext = new Core::IContext(&d->m_treeView);
+ d->m_taskWindowContext->setWidget(&d->m_treeView);
d->m_taskWindowContext->setContext(Core::Context(Core::Constants::C_PROBLEM_PANE));
Core::ICore::addContextObject(d->m_taskWindowContext);
- connect(d->m_listview->selectionModel(), &QItemSelectionModel::currentChanged,
- tld, &TaskDelegate::currentChanged);
- connect(d->m_listview->selectionModel(), &QItemSelectionModel::currentChanged,
- this, [this](const QModelIndex &index) { d->m_listview->scrollTo(index); });
- connect(d->m_listview, &QAbstractItemView::activated,
+ connect(d->m_treeView.selectionModel(), &QItemSelectionModel::currentChanged,
+ this, [this](const QModelIndex &index) { d->m_treeView.scrollTo(index); });
+ connect(&d->m_treeView, &QAbstractItemView::activated,
this, &TaskWindow::triggerDefaultHandler);
- connect(d->m_listview->selectionModel(), &QItemSelectionModel::selectionChanged,
+ connect(d->m_treeView.selectionModel(), &QItemSelectionModel::selectionChanged,
this, [this] {
- const Tasks tasks = d->m_filter->tasks(d->m_listview->selectionModel()->selectedIndexes());
+ const Tasks tasks = d->m_filter->tasks(d->m_treeView.selectionModel()->selectedIndexes());
for (QAction * const action : std::as_const(d->m_actions)) {
ITaskHandler * const h = d->handler(action);
action->setEnabled(h && h->canHandle(tasks));
}
});
- d->m_contextMenu = new QMenu(d->m_listview);
-
- d->m_listview->setContextMenuPolicy(Qt::ActionsContextMenu);
+ d->m_treeView.setContextMenuPolicy(Qt::ActionsContextMenu);
d->m_filterWarningsButton = createFilterButton(
Utils::Icons::WARNING_TOOLBAR.icon(),
@@ -365,7 +216,7 @@ TaskWindow::TaskWindow() : d(std::make_unique<TaskWindowPrivate>())
d->m_categoriesButton = new QToolButton;
d->m_categoriesButton->setIcon(Utils::Icons::FILTER.icon());
d->m_categoriesButton->setToolTip(Tr::tr("Filter by categories"));
- d->m_categoriesButton->setProperty("noArrow", true);
+ d->m_categoriesButton->setProperty(StyleHelper::C_NO_ARROW, true);
d->m_categoriesButton->setPopupMode(QToolButton::InstantPopup);
d->m_categoriesMenu = new QMenu(d->m_categoriesButton);
@@ -411,7 +262,6 @@ TaskWindow::TaskWindow() : d(std::make_unique<TaskWindowPrivate>())
TaskWindow::~TaskWindow()
{
delete d->m_filterWarningsButton;
- delete d->m_listview;
delete d->m_filter;
delete d->m_model;
}
@@ -435,7 +285,7 @@ void TaskWindow::delayedInitialization()
connect(action, &QAction::triggered, this, [this, action] {
ITaskHandler *h = d->handler(action);
if (h)
- h->handle(d->m_filter->tasks(d->m_listview->selectionModel()->selectedIndexes()));
+ h->handle(d->m_filter->tasks(d->m_treeView.selectionModel()->selectedIndexes()));
});
d->m_actions << action;
@@ -445,7 +295,7 @@ void TaskWindow::delayedInitialization()
Core::ActionManager::registerAction(action, id, d->m_taskWindowContext->context(), true);
action = cmd->action();
}
- d->m_listview->addAction(action);
+ d->m_treeView.addAction(action);
}
}
@@ -461,7 +311,7 @@ QString TaskWindow::displayName() const
QWidget *TaskWindow::outputWidget(QWidget *)
{
- return d->m_listview;
+ return &d->m_treeView;
}
void TaskWindow::clearTasks(Id categoryId)
@@ -565,7 +415,7 @@ void TaskWindow::showTask(const Task &task)
int sourceRow = d->m_model->rowForTask(task);
QModelIndex sourceIdx = d->m_model->index(sourceRow, 0);
QModelIndex filterIdx = d->m_filter->mapFromSource(sourceIdx);
- d->m_listview->setCurrentIndex(filterIdx);
+ d->m_treeView.setCurrentIndex(filterIdx);
popup(Core::IOutputPane::ModeSwitch);
}
@@ -582,7 +432,10 @@ void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
if (!index.isValid() || !d->m_defaultHandler)
return;
- Task task(d->m_filter->task(index));
+ QModelIndex taskIndex = index;
+ if (index.parent().isValid())
+ taskIndex = index.parent();
+ Task task(d->m_filter->task(taskIndex));
if (task.isNull())
return;
@@ -599,7 +452,7 @@ void TaskWindow::triggerDefaultHandler(const QModelIndex &index)
d->m_defaultHandler->handle(task);
} else {
if (!task.file.exists())
- d->m_model->setFileNotFound(index, true);
+ d->m_model->setFileNotFound(taskIndex, true);
}
}
@@ -665,7 +518,7 @@ void TaskWindow::clearContents()
bool TaskWindow::hasFocus() const
{
- return d->m_listview->window()->focusWidget() == d->m_listview;
+ return d->m_treeView.window()->focusWidget() == &d->m_treeView;
}
bool TaskWindow::canFocus() const
@@ -676,9 +529,13 @@ bool TaskWindow::canFocus() const
void TaskWindow::setFocus()
{
if (d->m_filter->rowCount()) {
- d->m_listview->setFocus();
- if (d->m_listview->currentIndex() == QModelIndex())
- d->m_listview->setCurrentIndex(d->m_filter->index(0,0, QModelIndex()));
+ d->m_treeView.setFocus();
+ if (!d->m_treeView.currentIndex().isValid())
+ d->m_treeView.setCurrentIndex(d->m_filter->index(0,0, QModelIndex()));
+ if (d->m_treeView.selectionModel()->selection().isEmpty()) {
+ d->m_treeView.selectionModel()->setCurrentIndex(d->m_treeView.currentIndex(),
+ QItemSelectionModel::Select);
+ }
}
}
@@ -696,7 +553,7 @@ void TaskWindow::goToNext()
{
if (!canNext())
return;
- QModelIndex startIndex = d->m_listview->currentIndex();
+ QModelIndex startIndex = d->m_treeView.currentIndex();
QModelIndex currentIndex = startIndex;
if (startIndex.isValid()) {
@@ -711,7 +568,7 @@ void TaskWindow::goToNext()
} else {
currentIndex = d->m_filter->index(0, 0);
}
- d->m_listview->setCurrentIndex(currentIndex);
+ d->m_treeView.setCurrentIndex(currentIndex);
triggerDefaultHandler(currentIndex);
}
@@ -719,7 +576,7 @@ void TaskWindow::goToPrev()
{
if (!canPrevious())
return;
- QModelIndex startIndex = d->m_listview->currentIndex();
+ QModelIndex startIndex = d->m_treeView.currentIndex();
QModelIndex currentIndex = startIndex;
if (startIndex.isValid()) {
@@ -734,7 +591,7 @@ void TaskWindow::goToPrev()
} else {
currentIndex = d->m_filter->index(0, 0);
}
- d->m_listview->setCurrentIndex(currentIndex);
+ d->m_treeView.setCurrentIndex(currentIndex);
triggerDefaultHandler(currentIndex);
}
@@ -749,268 +606,167 @@ bool TaskWindow::canNavigate() const
return true;
}
-/////
-// Delegate
-/////
-
-TaskDelegate::TaskDelegate(QObject *parent) :
- QStyledItemDelegate(parent)
-{ }
-
-TaskDelegate::~TaskDelegate() = default;
-
-QSize TaskDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
{
- QStyleOptionViewItem opt = option;
- initStyleOption(&opt, index);
-
- auto view = qobject_cast<const QAbstractItemView *>(opt.widget);
- const bool current = view->selectionModel()->currentIndex() == index;
- QSize s;
- s.setWidth(option.rect.width());
-
- if (!current && option.font == m_cachedFont && m_cachedHeight > 0) {
- s.setHeight(m_cachedHeight);
- return s;
+ if (!needsSpecialHandling(index)) {
+ QStyledItemDelegate::paint(painter, option, index);
+ return;
}
- QFontMetrics fm(option.font);
- int fontHeight = fm.height();
- int fontLeading = fm.leading();
-
- auto model = static_cast<TaskFilterModel *>(view->model())->taskModel();
- Positions positions(option, model);
-
- if (current) {
- QString description = index.data(TaskModel::Description).toString();
- // Layout the description
- int leading = fontLeading;
- int height = 0;
- description.replace(QLatin1Char('\n'), QChar::LineSeparator);
- QTextLayout tl(description);
- tl.setFormats(index.data(TaskModel::Task_t).value<Task>().formats);
- tl.beginLayout();
- while (true) {
- QTextLine line = tl.createLine();
- if (!line.isValid())
- break;
- line.setLineWidth(positions.textAreaWidth());
- height += leading;
- line.setPosition(QPoint(0, height));
- height += static_cast<int>(line.height());
- }
- tl.endLayout();
+ QStyleOptionViewItem options = option;
+ initStyleOption(&options, index);
- s.setHeight(height + leading + fontHeight + 3);
- } else {
- s.setHeight(fontHeight + 3);
+ painter->save();
+ m_doc.setHtml(options.text);
+ options.text = "";
+ options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
+ painter->translate(options.rect.left(), options.rect.top());
+ QRect clip(0, 0, options.rect.width(), options.rect.height());
+ QAbstractTextDocumentLayout::PaintContext paintContext;
+ paintContext.palette = options.palette;
+ painter->setClipRect(clip);
+ paintContext.clip = clip;
+ if (qobject_cast<const QAbstractItemView *>(options.widget)
+ ->selectionModel()->isSelected(index)) {
+ QAbstractTextDocumentLayout::Selection selection;
+ selection.cursor = QTextCursor(&m_doc);
+ selection.cursor.select(QTextCursor::Document);
+ selection.format.setBackground(options.palette.brush(QPalette::Highlight));
+ selection.format.setForeground(options.palette.brush(QPalette::HighlightedText));
+ paintContext.selections << selection;
}
- if (s.height() < Positions::minimumHeight())
- s.setHeight(Positions::minimumHeight());
+ m_doc.documentLayout()->draw(painter, paintContext);
+ painter->restore();
+}
- if (!current) {
- m_cachedHeight = s.height();
- m_cachedFont = option.font;
- }
+QSize TaskDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ if (!needsSpecialHandling(index))
+ return QStyledItemDelegate::sizeHint(option, index);
- return s;
+ QStyleOptionViewItem options = option;
+ initStyleOption(&options, index);
+ m_doc.setHtml(options.text);
+ m_doc.setTextWidth(options.rect.width());
+ return QSize(m_doc.idealWidth(), m_doc.size().height());
}
-void TaskDelegate::emitSizeHintChanged(const QModelIndex &index)
+bool TaskDelegate::needsSpecialHandling(const QModelIndex &index) const
{
- emit sizeHintChanged(index);
+ QModelIndex sourceIndex = index;
+ if (const auto proxyModel = qobject_cast<const QAbstractProxyModel *>(index.model()))
+ sourceIndex = proxyModel->mapToSource(index);
+ return sourceIndex.internalId();
}
-void TaskDelegate::currentChanged(const QModelIndex &current, const QModelIndex &previous)
+TaskView::TaskView()
{
- m_hrefs.clear();
- emit sizeHintChanged(current);
- emit sizeHintChanged(previous);
+ setMouseTracking(true);
+ setVerticalScrollMode(ScrollPerPixel);
}
-QString TaskDelegate::hrefForPos(const QPointF &pos)
+void TaskView::resizeColumns()
{
- for (const auto &link : std::as_const(m_hrefs)) {
- if (link.first.contains(pos))
- return link.second;
- }
- return {};
+ setColumnWidth(0, width() * 0.85);
+ setColumnWidth(1, width() * 0.15);
}
-void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void TaskView::resizeEvent(QResizeEvent *e)
{
- QStyleOptionViewItem opt = option;
- initStyleOption(&opt, index);
- painter->save();
+ TreeView::resizeEvent(e);
+ resizeColumns();
+}
- QFontMetrics fm(opt.font);
- QColor backgroundColor;
- QColor textColor;
+void TaskView::mousePressEvent(QMouseEvent *e)
+{
+ m_clickAnchor = anchorAt(e->pos());
+ if (m_clickAnchor.isEmpty())
+ TreeView::mousePressEvent(e);
+}
- auto view = qobject_cast<const QAbstractItemView *>(opt.widget);
- const bool selected = view->selectionModel()->isSelected(index);
- const bool current = view->selectionModel()->currentIndex() == index;
+void TaskView::mouseMoveEvent(QMouseEvent *e)
+{
+ const QString anchor = anchorAt(e->pos());
+ if (m_clickAnchor != anchor)
+ m_clickAnchor.clear();
+ if (m_hoverAnchor != anchor) {
+ m_hoverAnchor = anchor;
+ if (!m_hoverAnchor.isEmpty())
+ setCursor(Qt::PointingHandCursor);
+ else
+ unsetCursor();
+ }
+}
- if (selected) {
- painter->setBrush(opt.palette.highlight().color());
- backgroundColor = opt.palette.highlight().color();
- } else {
- painter->setBrush(opt.palette.window().color());
- backgroundColor = opt.palette.window().color();
+void TaskView::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (m_clickAnchor.isEmpty() || e->button() == Qt::RightButton) {
+ TreeView::mouseReleaseEvent(e);
+ return;
}
- painter->setPen(Qt::NoPen);
- painter->drawRect(opt.rect);
- // Set Text Color
- if (selected)
- textColor = opt.palette.highlightedText().color();
- else
- textColor = opt.palette.text().color();
-
- painter->setPen(textColor);
-
- auto model = static_cast<TaskFilterModel *>(view->model())->taskModel();
- Positions positions(opt, model);
-
- // Paint TaskIconArea:
- QIcon icon = index.data(TaskModel::Icon).value<QIcon>();
- painter->drawPixmap(positions.left(), positions.top(),
- icon.pixmap(Positions::taskIconWidth(), Positions::taskIconHeight()));
-
- // Paint TextArea:
- if (!current) {
- // in small mode we lay out differently
- QString bottom = index.data(TaskModel::Description).toString().split(QLatin1Char('\n')).first();
- painter->setClipRect(positions.textArea());
- painter->drawText(positions.textAreaLeft(), positions.top() + fm.ascent(), bottom);
- if (fm.horizontalAdvance(bottom) > positions.textAreaWidth()) {
- // draw a gradient to mask the text
- int gradientStart = positions.textAreaRight() - ELLIPSIS_GRADIENT_WIDTH + 1;
- QLinearGradient lg(gradientStart, 0, gradientStart + ELLIPSIS_GRADIENT_WIDTH, 0);
- lg.setColorAt(0, Qt::transparent);
- lg.setColorAt(1, backgroundColor);
- painter->fillRect(gradientStart, positions.top(), ELLIPSIS_GRADIENT_WIDTH, positions.firstLineHeight(), lg);
- }
- } else {
- // Description
- QString description = index.data(TaskModel::Description).toString();
- // Layout the description
- int leading = fm.leading();
- int height = 0;
- description.replace(QLatin1Char('\n'), QChar::LineSeparator);
- QTextLayout tl(description);
- QVector<QTextLayout::FormatRange> formats = index.data(TaskModel::Task_t).value<Task>().formats;
- for (QTextLayout::FormatRange &format : formats)
- format.format.setForeground(textColor);
- tl.setFormats(formats);
- tl.beginLayout();
- while (true) {
- QTextLine line = tl.createLine();
- if (!line.isValid())
- break;
- line.setLineWidth(positions.textAreaWidth());
- height += leading;
- line.setPosition(QPoint(0, height));
- height += static_cast<int>(line.height());
- }
- tl.endLayout();
- const QPoint indexPos = view->visualRect(index).topLeft();
- tl.draw(painter, QPoint(positions.textAreaLeft(), positions.top()));
- m_hrefs.clear();
- for (const auto &range : tl.formats()) {
- if (!range.format.isAnchor())
- continue;
- const QTextLine &firstLinkLine = tl.lineForTextPosition(range.start);
- const QTextLine &lastLinkLine = tl.lineForTextPosition(range.start + range.length - 1);
- for (int i = firstLinkLine.lineNumber(); i <= lastLinkLine.lineNumber(); ++i) {
- const QTextLine &linkLine = tl.lineAt(i);
- if (!linkLine.isValid())
- break;
- const QPointF linePos = linkLine.position();
- const int linkStartPos = i == firstLinkLine.lineNumber()
- ? range.start : linkLine.textStart();
- const qreal startOffset = linkLine.cursorToX(linkStartPos);
- const int linkEndPos = i == lastLinkLine.lineNumber()
- ? range.start + range.length
- : linkLine.textStart() + linkLine.textLength();
- const qreal endOffset = linkLine.cursorToX(linkEndPos);
- const QPointF linkPos(indexPos.x() + positions.textAreaLeft() + linePos.x()
- + startOffset, positions.top() + linePos.y());
- const QSize linkSize(endOffset - startOffset, linkLine.height());
- const QRectF linkRect(linkPos, linkSize);
- m_hrefs.push_back({linkRect, range.format.anchorHref()});
- }
- }
+ const QString anchor = anchorAt(e->pos());
+ if (anchor == m_clickAnchor) {
+ Core::EditorManager::openEditorAt(OutputLineParser::parseLinkTarget(m_clickAnchor), {},
+ Core::EditorManager::SwitchSplitIfAlreadyVisible);
+ }
+ m_clickAnchor.clear();
+}
- const QColor mix = StyleHelper::mergedColors(textColor, backgroundColor, 70);
- const QString directory = QDir::toNativeSeparators(index.data(TaskModel::File).toString());
- int secondBaseLine = positions.top() + fm.ascent() + height + leading;
- if (index.data(TaskModel::FileNotFound).toBool() && !directory.isEmpty()) {
- const QString fileNotFound = Tr::tr("File not found: %1").arg(directory);
- const QColor errorColor = selected ? mix : creatorTheme()->color(Theme::TextColorError);
- painter->setPen(errorColor);
- painter->drawText(positions.textAreaLeft(), secondBaseLine, fileNotFound);
- } else {
- painter->setPen(mix);
- painter->drawText(positions.textAreaLeft(), secondBaseLine, directory);
+void TaskView::keyReleaseEvent(QKeyEvent *e)
+{
+ TreeView::keyReleaseEvent(e);
+ if (e->key() == Qt::Key_Space) {
+ const Task task = static_cast<TaskFilterModel *>(model())->task(currentIndex());
+ if (!task.isNull()) {
+ const QPoint toolTipPos = mapToGlobal(visualRect(currentIndex()).topLeft());
+ QMetaObject::invokeMethod(this, [this, task, toolTipPos] {
+ showToolTip(task, toolTipPos); }, Qt::QueuedConnection);
}
}
- painter->setPen(textColor);
-
- // Paint FileArea
- QString file = index.data(TaskModel::File).toString();
- const int pos = file.lastIndexOf(QLatin1Char('/'));
- if (pos != -1)
- file = file.mid(pos +1);
- const int realFileWidth = fm.horizontalAdvance(file);
- painter->setClipRect(positions.fileArea());
- painter->drawText(qMin(positions.fileAreaLeft(), positions.fileAreaRight() - realFileWidth),
- positions.top() + fm.ascent(), file);
- if (realFileWidth > positions.fileAreaWidth()) {
- // draw a gradient to mask the text
- int gradientStart = positions.fileAreaLeft() - 1;
- QLinearGradient lg(gradientStart + ELLIPSIS_GRADIENT_WIDTH, 0, gradientStart, 0);
- lg.setColorAt(0, Qt::transparent);
- lg.setColorAt(1, backgroundColor);
- painter->fillRect(gradientStart, positions.top(), ELLIPSIS_GRADIENT_WIDTH, positions.firstLineHeight(), lg);
- }
+}
- // Paint LineArea
- int line = index.data(TaskModel::Line).toInt();
- int movedLine = index.data(TaskModel::MovedLine).toInt();
- QString lineText;
-
- if (line == -1) {
- // No line information at all
- } else if (movedLine == -1) {
- // removed the line, but we had line information, show the line in ()
- QFont f = painter->font();
- f.setItalic(true);
- painter->setFont(f);
- lineText = QLatin1Char('(') + QString::number(line) + QLatin1Char(')');
- } else if (movedLine != line) {
- // The line was moved
- QFont f = painter->font();
- f.setItalic(true);
- painter->setFont(f);
- lineText = QString::number(movedLine);
- } else {
- lineText = QString::number(line);
+bool TaskView::event(QEvent *e)
+{
+ if (e->type() != QEvent::ToolTip)
+ return TreeView::event(e);
+
+ const auto helpEvent = static_cast<QHelpEvent*>(e);
+ const Task task = static_cast<TaskFilterModel *>(model())->task(indexAt(helpEvent->pos()));
+ if (task.isNull())
+ return TreeView::event(e);
+ showToolTip(task, helpEvent->globalPos());
+ e->accept();
+ return true;
+}
+
+void TaskView::showToolTip(const Task &task, const QPoint &pos)
+{
+ if (task.details.isEmpty()) {
+ ToolTip::hideImmediately();
+ return;
}
- painter->setClipRect(positions.lineArea());
- const int realLineWidth = fm.horizontalAdvance(lineText);
- painter->drawText(positions.lineAreaRight() - realLineWidth, positions.top() + fm.ascent(), lineText);
- painter->setClipRect(opt.rect);
+ const auto layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(new QLabel(task.formattedDescription({})));
+ ToolTip::show(pos, layout);
+}
- // Separator lines
- painter->setPen(QColor::fromRgb(150,150,150));
- const QRectF borderRect = QRectF(opt.rect).adjusted(0.5, 0.5, -0.5, -0.5);
- painter->drawLine(borderRect.bottomLeft(), borderRect.bottomRight());
- painter->restore();
+QString TaskView::anchorAt(const QPoint &pos)
+{
+ const QModelIndex index = indexAt(pos);
+ if (!index.isValid() || !index.internalId())
+ return {};
+
+ const QRect itemRect = visualRect(index);
+ QTextDocument &doc = static_cast<TaskDelegate *>(itemDelegate())->doc();
+ doc.setHtml(model()->data(index, Qt::DisplayRole).toString());
+ const QAbstractTextDocumentLayout * const textLayout = doc.documentLayout();
+ QTC_ASSERT(textLayout, return {});
+ return textLayout->anchorAt(pos - itemRect.topLeft());
}
} // namespace Internal
} // namespace ProjectExplorer
-
-#include "taskwindow.moc"
diff --git a/src/plugins/projectexplorer/testdata/multi-target-project/CMakeLists.txt b/src/plugins/projectexplorer/testdata/multi-target-project/CMakeLists.txt
new file mode 100644
index 0000000000..5313539cd7
--- /dev/null
+++ b/src/plugins/projectexplorer/testdata/multi-target-project/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(multi-target-project)
+add_executable(multi-target-project-app multi-target-project-main.cpp multi-target-project-shared.h)
+add_library(multi-target-project-lib STATIC multi-target-project-lib.cpp multi-target-project-shared.h)
diff --git a/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-app.pro b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-app.pro
new file mode 100644
index 0000000000..96870c05c1
--- /dev/null
+++ b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-app.pro
@@ -0,0 +1,4 @@
+TARGET = app
+CONFIG -= qt
+SOURCES = multi-target-project-main.cpp
+HEADERS = multi-target-project-shared.h
diff --git a/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-lib.cpp b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-lib.cpp
new file mode 100644
index 0000000000..9b7a34861c
--- /dev/null
+++ b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-lib.cpp
@@ -0,0 +1,6 @@
+#include "multi-target-project-shared.h"
+
+int increaseNumber()
+{
+ return getNumber() + 1;
+}
diff --git a/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-lib.pro b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-lib.pro
new file mode 100644
index 0000000000..4257154051
--- /dev/null
+++ b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-lib.pro
@@ -0,0 +1,4 @@
+TEMPLATE = lib
+CONFIG += static
+SOURCES = multi-target-project-lib.cpp
+HEADERS = multi-target-project-shared.h
diff --git a/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-main.cpp b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-main.cpp
new file mode 100644
index 0000000000..306400b350
--- /dev/null
+++ b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-main.cpp
@@ -0,0 +1,6 @@
+#include "multi-target-project-shared.h"
+
+int main()
+{
+ return getNumber();
+}
diff --git a/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-shared.h b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-shared.h
new file mode 100644
index 0000000000..9f839e82d0
--- /dev/null
+++ b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project-shared.h
@@ -0,0 +1,3 @@
+#pragma once
+
+inline int getNumber() { return 5; }
diff --git a/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project.pro b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project.pro
new file mode 100644
index 0000000000..5e6289d7b2
--- /dev/null
+++ b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+app.file = multi-target-project-app.pro
+lib.file = multi-target-project-lib.pro
+SUBDIRS = app lib
diff --git a/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project.qbs b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project.qbs
new file mode 100644
index 0000000000..079ac82c95
--- /dev/null
+++ b/src/plugins/projectexplorer/testdata/multi-target-project/multi-target-project.qbs
@@ -0,0 +1,10 @@
+Project {
+ CppApplication {
+ name: "app"
+ files: ["multi-target-project-main.cpp", "multi-target-project-shared.h"]
+ }
+ StaticLibrary {
+ Depends { name: "cpp" }
+ files: ["multi-target-project-lib.cpp", "multi-target-project-shared.h"]
+ }
+}
diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp
index 1a3d3d43f5..8b8cfce2c8 100644
--- a/src/plugins/projectexplorer/toolchain.cpp
+++ b/src/plugins/projectexplorer/toolchain.cpp
@@ -192,7 +192,7 @@ bool ToolChain::isValid() const
return d->m_isValid.value_or(false);
}
-QStringList ToolChain::includedFiles(const QStringList &flags, const QString &directory) const
+FilePaths ToolChain::includedFiles(const QStringList &flags, const FilePath &directory) const
{
Q_UNUSED(flags)
Q_UNUSED(directory)
@@ -466,12 +466,12 @@ Utils::LanguageVersion ToolChain::languageVersion(const Utils::Id &language, con
}
}
-QStringList ToolChain::includedFiles(const QString &option,
- const QStringList &flags,
- const QString &directoryPath,
- PossiblyConcatenatedFlag possiblyConcatenated)
+FilePaths ToolChain::includedFiles(const QString &option,
+ const QStringList &flags,
+ const FilePath &directoryPath,
+ PossiblyConcatenatedFlag possiblyConcatenated)
{
- QStringList result;
+ FilePaths result;
for (int i = 0; i < flags.size(); ++i) {
QString includeFile;
@@ -484,11 +484,8 @@ QStringList ToolChain::includedFiles(const QString &option,
if (includeFile.isEmpty() && flag == option && i + 1 < flags.size())
includeFile = flags[++i];
- if (!includeFile.isEmpty()) {
- if (!QFileInfo(includeFile).isAbsolute())
- includeFile = directoryPath + "/" + includeFile;
- result.append(QDir::cleanPath(includeFile));
- }
+ if (!includeFile.isEmpty())
+ result.append(directoryPath.resolvePath(includeFile));
}
return result;
@@ -677,7 +674,9 @@ ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown,
const IDevice::ConstPtr &device,
const FilePaths &searchPaths)
: alreadyKnown(alreadyKnown), device(device), searchPaths(searchPaths)
-{}
+{
+ QTC_CHECK(device);
+}
BadToolchain::BadToolchain(const Utils::FilePath &filePath)
: BadToolchain(filePath, filePath.symLinkTarget(), filePath.lastModified())
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index 15bee2fdaa..35cad5333e 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -102,7 +102,7 @@ public:
virtual Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const = 0;
virtual Utils::WarningFlags warningFlags(const QStringList &cflags) const = 0;
- virtual QStringList includedFiles(const QStringList &flags, const QString &directory) const;
+ virtual Utils::FilePaths includedFiles(const QStringList &flags, const Utils::FilePath &directory) const;
virtual QString sysRoot() const;
QString explicitCodeModelTargetTriple() const;
@@ -184,10 +184,10 @@ protected:
virtual bool fromMap(const QVariantMap &data);
enum class PossiblyConcatenatedFlag { No, Yes };
- static QStringList includedFiles(const QString &option,
- const QStringList &flags,
- const QString &directoryPath,
- PossiblyConcatenatedFlag possiblyConcatenated);
+ static Utils::FilePaths includedFiles(const QString &option,
+ const QStringList &flags,
+ const Utils::FilePath &directoryPath,
+ PossiblyConcatenatedFlag possiblyConcatenated);
private:
ToolChain(const ToolChain &) = delete;
diff --git a/src/plugins/projectexplorer/toolchainconfigwidget.cpp b/src/plugins/projectexplorer/toolchainconfigwidget.cpp
index ef97ad72cf..84b80b4e04 100644
--- a/src/plugins/projectexplorer/toolchainconfigwidget.cpp
+++ b/src/plugins/projectexplorer/toolchainconfigwidget.cpp
@@ -7,8 +7,8 @@
#include "projectexplorertr.h"
#include <utils/detailswidget.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <QFormLayout>
#include <QLineEdit>
diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp
index b8df603850..e0717ab780 100644
--- a/src/plugins/projectexplorer/toolchainoptionspage.cpp
+++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp
@@ -48,20 +48,8 @@ class ToolChainTreeItem : public TreeItem
{
public:
ToolChainTreeItem(QStackedWidget *parentWidget, ToolChain *tc, bool c) :
- toolChain(tc), changed(c)
- {
- widget = tc->createConfigurationWidget().release();
- if (widget) {
- parentWidget->addWidget(widget);
- if (tc->isAutoDetected())
- widget->makeReadOnly();
- QObject::connect(widget, &ToolChainConfigWidget::dirty,
- [this] {
- changed = true;
- update();
- });
- }
- }
+ toolChain(tc), changed(c), m_parentWidget(parentWidget)
+ {}
QVariant data(int column, int role) const override
{
@@ -93,9 +81,30 @@ public:
return QVariant();
}
+ ToolChainConfigWidget *widget()
+ {
+ if (!m_widget) {
+ m_widget = toolChain->createConfigurationWidget().release();
+ if (m_widget) {
+ m_parentWidget->addWidget(m_widget);
+ if (toolChain->isAutoDetected())
+ m_widget->makeReadOnly();
+ QObject::connect(m_widget, &ToolChainConfigWidget::dirty,
+ [this] {
+ changed = true;
+ update();
+ });
+ }
+ }
+ return m_widget;
+ }
+
ToolChain *toolChain;
- ToolChainConfigWidget *widget;
bool changed;
+
+private:
+ ToolChainConfigWidget *m_widget = nullptr;
+ QStackedWidget *m_parentWidget = nullptr;
};
class DetectionSettingsDialog : public QDialog
@@ -423,7 +432,7 @@ void ToolChainOptionsWidget::toolChainSelectionChanged()
{
ToolChainTreeItem *item = currentTreeItem();
- QWidget *currentTcWidget = item ? item->widget : nullptr;
+ QWidget *currentTcWidget = item ? item->widget() : nullptr;
if (currentTcWidget)
m_widgetStack->setCurrentWidget(currentTcWidget);
m_container->setVisible(currentTcWidget);
@@ -447,8 +456,8 @@ void ToolChainOptionsWidget::apply()
for (TreeItem *item : *parent) {
auto tcItem = static_cast<ToolChainTreeItem *>(item);
Q_ASSERT(tcItem->toolChain);
- if (!tcItem->toolChain->isAutoDetected() && tcItem->widget && tcItem->changed)
- tcItem->widget->apply();
+ if (!tcItem->toolChain->isAutoDetected() && tcItem->widget() && tcItem->changed)
+ tcItem->widget()->apply();
tcItem->changed = false;
tcItem->update();
}
diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
index 4152e9882e..35224e4d02 100644
--- a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
+++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
@@ -3,6 +3,7 @@
#include "toolchainsettingsaccessor.h"
+#include "devicesupport/devicemanager.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
#include "toolchain.h"
@@ -168,11 +169,10 @@ static ToolChainOperations mergeToolChainLists(const Toolchains &systemFileTcs,
// ToolChainSettingsAccessor:
// --------------------------------------------------------------------
-ToolChainSettingsAccessor::ToolChainSettingsAccessor() :
- UpgradingSettingsAccessor("QtCreatorToolChains",
- Tr::tr("Tool Chains"),
- Core::Constants::IDE_DISPLAY_NAME)
+ToolChainSettingsAccessor::ToolChainSettingsAccessor()
{
+ setDocType("QtCreatorToolChains");
+ setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME);
setBaseFilePath(Core::ICore::userResourcePath(TOOLCHAIN_FILENAME));
addVersionUpgrader(std::make_unique<ToolChainSettingsUpgraderV0>());
@@ -192,9 +192,11 @@ Toolchains ToolChainSettingsAccessor::restoreToolChains(QWidget *parent) const
// Autodetect: Pass autodetected toolchains from user file so the information can be reused:
const Toolchains autodetectedUserFileTcs
= Utils::filtered(userFileTcs, &ToolChain::isAutoDetected);
- // FIXME: Use real device?
- const Toolchains autodetectedTcs =
- autoDetectToolChains(ToolchainDetector(autodetectedUserFileTcs, {}, {}));
+
+ // Autodect from system paths on the desktop device.
+ // The restriction is intentional to keep startup and automatic validation a limited effort
+ ToolchainDetector detector(autodetectedUserFileTcs, DeviceManager::defaultDesktopDevice(), {});
+ const Toolchains autodetectedTcs = autoDetectToolChains(detector);
// merge tool chains and register those that we need to keep:
const ToolChainOperations ops = mergeToolChainLists(systemFileTcs, userFileTcs, autodetectedTcs);
diff --git a/src/plugins/projectexplorer/treescanner.cpp b/src/plugins/projectexplorer/treescanner.cpp
index abcc66c3cc..294ef4988e 100644
--- a/src/plugins/projectexplorer/treescanner.cpp
+++ b/src/plugins/projectexplorer/treescanner.cpp
@@ -9,9 +9,9 @@
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
+#include <utils/async.h>
#include <utils/qtcassert.h>
#include <utils/algorithm.h>
-#include <utils/runextensions.h>
#include <memory>
@@ -42,9 +42,9 @@ bool TreeScanner::asyncScanForFiles(const Utils::FilePath &directory)
if (!m_futureWatcher.isFinished())
return false;
- m_scanFuture = Utils::runAsync(
- [directory, filter = m_filter, factory = m_factory] (FutureInterface &fi) {
- TreeScanner::scanForFiles(fi, directory, filter, factory);
+ m_scanFuture = Utils::asyncRun(
+ [directory, filter = m_filter, factory = m_factory] (Promise &promise) {
+ TreeScanner::scanForFiles(promise, directory, filter, factory);
});
m_futureWatcher.setFuture(m_scanFuture);
@@ -139,10 +139,10 @@ static std::unique_ptr<FolderNode> createFolderNode(const Utils::FilePath &direc
return fileSystemNode;
}
-void TreeScanner::scanForFiles(FutureInterface &fi, const Utils::FilePath& directory,
+void TreeScanner::scanForFiles(Promise &promise, const Utils::FilePath& directory,
const FileFilter &filter, const FileTypeFactory &factory)
{
- QList<FileNode *> nodes = ProjectExplorer::scanForFiles(fi, directory,
+ QList<FileNode *> nodes = ProjectExplorer::scanForFiles(promise, directory,
[&filter, &factory](const Utils::FilePath &fn) -> FileNode * {
const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn);
@@ -160,10 +160,10 @@ void TreeScanner::scanForFiles(FutureInterface &fi, const Utils::FilePath& direc
Utils::sort(nodes, ProjectExplorer::Node::sortByPath);
- fi.setProgressValue(fi.progressMaximum());
+ promise.setProgressValue(promise.future().progressMaximum());
Result result{createFolderNode(directory, nodes), nodes};
- fi.reportResult(result);
+ promise.addResult(result);
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/treescanner.h b/src/plugins/projectexplorer/treescanner.h
index e324303c17..f8d019121b 100644
--- a/src/plugins/projectexplorer/treescanner.h
+++ b/src/plugins/projectexplorer/treescanner.h
@@ -31,7 +31,7 @@ public:
};
using Future = QFuture<Result>;
using FutureWatcher = QFutureWatcher<Result>;
- using FutureInterface = QFutureInterface<Result>;
+ using Promise = QPromise<Result>;
using FileFilter = std::function<bool(const Utils::MimeType &, const Utils::FilePath &)>;
using FileTypeFactory = std::function<ProjectExplorer::FileType(const Utils::MimeType &, const Utils::FilePath &)>;
@@ -69,7 +69,7 @@ signals:
void finished();
private:
- static void scanForFiles(FutureInterface &fi, const Utils::FilePath &directory,
+ static void scanForFiles(Promise &fi, const Utils::FilePath &directory,
const FileFilter &filter, const FileTypeFactory &factory);
private:
diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp
index cf347e032f..ae900ea818 100644
--- a/src/plugins/projectexplorer/userfileaccessor.cpp
+++ b/src/plugins/projectexplorer/userfileaccessor.cpp
@@ -18,8 +18,8 @@
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/persistentsettings.h>
+#include <utils/process.h>
#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
#include <QRegularExpression>
@@ -283,19 +283,21 @@ FilePaths UserFileBackUpStrategy::readFileCandidates(const FilePath &baseFileNam
// UserFileAccessor:
// --------------------------------------------------------------------
-UserFileAccessor::UserFileAccessor(Project *project) :
- MergingSettingsAccessor(std::make_unique<VersionedBackUpStrategy>(this),
- "QtCreatorProject", project->displayName(),
- Core::Constants::IDE_DISPLAY_NAME),
- m_project(project)
+UserFileAccessor::UserFileAccessor(Project *project)
+ : m_project(project)
{
+ setStrategy(std::make_unique<VersionedBackUpStrategy>(this));
+ setDocType("QtCreatorProject");
+ setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME);
+
// Setup:
const FilePath externalUser = externalUserFile();
const FilePath projectUser = projectUserFile();
setBaseFilePath(externalUser.isEmpty() ? projectUser : externalUser);
- auto secondary
- = std::make_unique<SettingsAccessor>(docType, displayName, applicationDisplayName);
+ auto secondary = std::make_unique<SettingsAccessor>();
+ secondary->setDocType(m_docType);
+ secondary->setApplicationDisplayName(m_applicationDisplayName);
secondary->setBaseFilePath(sharedFile());
secondary->setReadOnly();
setSecondaryAccessor(std::move(secondary));