1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "customexecutablerunconfiguration.h"
27 
28 #include "abi.h"
29 #include "buildconfiguration.h"
30 #include "devicesupport/devicemanager.h"
31 #include "environmentaspect.h"
32 #include "localenvironmentaspect.h"
33 #include "project.h"
34 #include "runcontrol.h"
35 #include "target.h"
36 
37 #include <coreplugin/icore.h>
38 
39 #include <utils/detailswidget.h>
40 #include <utils/pathchooser.h>
41 #include <utils/stringutils.h>
42 #include <utils/variablechooser.h>
43 
44 #include <QDialog>
45 #include <QDialogButtonBox>
46 #include <QDir>
47 #include <QFormLayout>
48 #include <QKeyEvent>
49 #include <QLabel>
50 #include <QLineEdit>
51 #include <QPushButton>
52 #include <QVBoxLayout>
53 
54 using namespace Utils;
55 
56 namespace ProjectExplorer {
57 
58 const char CUSTOM_EXECUTABLE_RUNCONFIG_ID[] = "ProjectExplorer.CustomExecutableRunConfiguration";
59 
60 // CustomExecutableRunConfiguration
61 
CustomExecutableRunConfiguration(Target * target)62 CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target)
63     : CustomExecutableRunConfiguration(target, CUSTOM_EXECUTABLE_RUNCONFIG_ID)
64 {}
65 
CustomExecutableRunConfiguration(Target * target,Utils::Id id)66 CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target, Utils::Id id)
67     : RunConfiguration(target, id)
68 {
69     auto envAspect = addAspect<LocalEnvironmentAspect>(target);
70 
71     auto exeAspect = addAspect<ExecutableAspect>();
72     exeAspect->setSettingsKey("ProjectExplorer.CustomExecutableRunConfiguration.Executable");
73     exeAspect->setDisplayStyle(StringAspect::PathChooserDisplay);
74     exeAspect->setHistoryCompleter("Qt.CustomExecutable.History");
75     exeAspect->setExpectedKind(PathChooser::ExistingCommand);
76     exeAspect->setEnvironment(envAspect->environment());
77 
78     addAspect<ArgumentsAspect>();
79     addAspect<WorkingDirectoryAspect>();
80     addAspect<TerminalAspect>();
81 
82     connect(envAspect, &EnvironmentAspect::environmentChanged,
83             this, [exeAspect, envAspect] { exeAspect->setEnvironment(envAspect->environment()); });
84 
85     setDefaultDisplayName(defaultDisplayName());
86 }
87 
rawExecutable() const88 QString CustomExecutableRunConfiguration::rawExecutable() const
89 {
90     return aspect<ExecutableAspect>()->executable().toString();
91 }
92 
isEnabled() const93 bool CustomExecutableRunConfiguration::isEnabled() const
94 {
95     return true;
96 }
97 
runnable() const98 Runnable CustomExecutableRunConfiguration::runnable() const
99 {
100     FilePath workingDirectory =
101             aspect<WorkingDirectoryAspect>()->workingDirectory(macroExpander());
102 
103     Runnable r;
104     r.setCommandLine(commandLine());
105     r.environment = aspect<EnvironmentAspect>()->environment();
106     r.workingDirectory = workingDirectory.toString();
107     r.device = DeviceManager::defaultDesktopDevice();
108 
109     if (!r.executable.isEmpty()) {
110         const QString expanded = macroExpander()->expand(r.executable.toString());
111         r.executable = r.environment.searchInPath(expanded, {workingDirectory});
112     }
113 
114     return r;
115 }
116 
defaultDisplayName() const117 QString CustomExecutableRunConfiguration::defaultDisplayName() const
118 {
119     if (rawExecutable().isEmpty())
120         return tr("Custom Executable");
121     else
122         return tr("Run %1").arg(QDir::toNativeSeparators(rawExecutable()));
123 }
124 
checkForIssues() const125 Tasks CustomExecutableRunConfiguration::checkForIssues() const
126 {
127     Tasks tasks;
128     if (rawExecutable().isEmpty()) {
129         tasks << createConfigurationIssue(tr("You need to set an executable in the custom run "
130                                              "configuration."));
131     }
132     return tasks;
133 }
134 
135 // Factories
136 
CustomExecutableRunConfigurationFactory()137 CustomExecutableRunConfigurationFactory::CustomExecutableRunConfigurationFactory() :
138     FixedRunConfigurationFactory(CustomExecutableRunConfiguration::tr("Custom Executable"))
139 {
140     registerRunConfiguration<CustomExecutableRunConfiguration>(CUSTOM_EXECUTABLE_RUNCONFIG_ID);
141 }
142 
CustomExecutableRunWorkerFactory()143 CustomExecutableRunWorkerFactory::CustomExecutableRunWorkerFactory()
144 {
145     setProduct<SimpleTargetRunner>();
146     addSupportedRunMode(Constants::NORMAL_RUN_MODE);
147     addSupportedRunConfig(CUSTOM_EXECUTABLE_RUNCONFIG_ID);
148 }
149 
150 } // namespace ProjectExplorer
151