diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index a44f605780e..39480e9a2c4 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -1070,6 +1071,19 @@ bool AndroidConfigurations::force32bitEmulator() return m_instance->m_force32bit; } +QProcessEnvironment AndroidConfigurations::toolsEnvironment(const AndroidConfig &config) +{ + Environment env = Environment::systemEnvironment(); + Utils::FileName jdkLocation = config.openJDKLocation(); + if (!jdkLocation.isEmpty()) { + env.set("JAVA_HOME", jdkLocation.toUserOutput()); + Utils::FileName binPath = jdkLocation; + binPath.appendPath("bin"); + env.prependOrSetPath(binPath.toUserOutput()); + } + return env.toProcessEnvironment(); +} + /** * Workaround for '????????????' serial numbers * @return ("-d") for buggy devices, ("-s", ) for normal diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 4565d5e3635..7424be1d14e 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -204,6 +205,7 @@ public: static void removeOldToolChains(); static void updateAutomaticKitList(); static bool force32bitEmulator(); + static QProcessEnvironment toolsEnvironment(const AndroidConfig &config); signals: void updated(); diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index 4adf95401ea..dd3895f507f 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -129,13 +129,14 @@ void watcherDeleter(QFutureWatcher *watcher) Runs the \c sdkmanger tool with arguments \a args. Returns \c true if the command is successfully executed. Output is copied into \a output. The function blocks the calling thread. */ -static bool sdkManagerCommand(const Utils::FileName &toolPath, const QStringList &args, +static bool sdkManagerCommand(const AndroidConfig &config, const QStringList &args, QString *output, int timeout = sdkManagerCmdTimeoutS) { SynchronousProcess proc; + proc.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(config)); proc.setTimeoutS(timeout); proc.setTimeOutMessageBoxEnabled(true); - SynchronousProcessResponse response = proc.run(toolPath.toString(), args); + SynchronousProcessResponse response = proc.run(config.sdkManagerToolPath().toString(), args); if (output) *output = response.allOutput(); return response.result == SynchronousProcessResponse::Finished; @@ -147,13 +148,14 @@ static bool sdkManagerCommand(const Utils::FileName &toolPath, const QStringList to cancel signal emmitted by \a sdkManager and kill the commands. The command is also killed after the lapse of \a timeout seconds. The function blocks the calling thread. */ -static void sdkManagerCommand(const Utils::FileName &toolPath, const QStringList &args, +static void sdkManagerCommand(const AndroidConfig &config, const QStringList &args, AndroidSdkManager &sdkManager, SdkCmdFutureInterface &fi, AndroidSdkManager::OperationOutput &output, double progressQuota, bool interruptible = true, int timeout = sdkManagerOperationTimeoutS) { int offset = fi.progressValue(); SynchronousProcess proc; + proc.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(config)); bool assertionFound = false; proc.setStdErrBufferedSignalsEnabled(true); proc.setStdOutBufferedSignalsEnabled(true); @@ -173,7 +175,7 @@ static void sdkManagerCommand(const Utils::FileName &toolPath, const QStringList QObject::connect(&sdkManager, &AndroidSdkManager::cancelActiveOperations, &proc, &SynchronousProcess::terminate); } - SynchronousProcessResponse response = proc.run(toolPath.toString(), args); + SynchronousProcessResponse response = proc.run(config.sdkManagerToolPath().toString(), args); if (assertionFound) { output.success = false; output.stdOutput = response.stdOut(); @@ -769,7 +771,7 @@ void AndroidSdkManagerPrivate::reloadSdkPackages() QString packageListing; QStringList args({"--list", "--verbose"}); args << m_config.sdkManagerToolArgs(); - if (sdkManagerCommand(m_config.sdkManagerToolPath(), args, &packageListing)) { + if (sdkManagerCommand(m_config, args, &packageListing)) { SdkManagerOutputParser parser(m_allPackages); parser.parsePackageListing(packageListing); } @@ -797,7 +799,7 @@ void AndroidSdkManagerPrivate::updateInstalled(SdkCmdFutureInterface &fi) QStringList args("--update"); args << m_config.sdkManagerToolArgs(); if (!fi.isCanceled()) - sdkManagerCommand(m_config.sdkManagerToolPath(), args, m_sdkManager, fi, result, 100); + sdkManagerCommand(m_config, args, m_sdkManager, fi, result, 100); else qCDebug(sdkManagerLog) << "Update: Operation cancelled before start"; @@ -826,12 +828,10 @@ void AndroidSdkManagerPrivate::update(SdkCmdFutureInterface &fi, const QStringLi result.stdOutput = QString("%1 %2").arg(isInstall ? installTag : uninstallTag) .arg(packagePath); fi.reportResult(result); - if (fi.isCanceled()) { + if (fi.isCanceled()) qCDebug(sdkManagerLog) << args << "Update: Operation cancelled before start"; - } else { - sdkManagerCommand(m_config.sdkManagerToolPath(), args, m_sdkManager, fi, result, - progressQuota, isInstall); - } + else + sdkManagerCommand(m_config, args, m_sdkManager, fi, result, progressQuota, isInstall); currentProgress += progressQuota; fi.setProgressValue(currentProgress); if (result.stdError.isEmpty() && !result.success) @@ -869,7 +869,7 @@ void AndroidSdkManagerPrivate::checkPendingLicense(SdkCmdFutureInterface &fi) result.type = AndroidSdkManager::LicenseCheck; QStringList args("--licenses"); if (!fi.isCanceled()) - sdkManagerCommand(m_config.sdkManagerToolPath(), args, m_sdkManager, fi, result, 100.0); + sdkManagerCommand(m_config, args, m_sdkManager, fi, result, 100.0); else qCDebug(sdkManagerLog) << "Update: Operation cancelled before start"; @@ -884,6 +884,7 @@ void AndroidSdkManagerPrivate::getPendingLicense(SdkCmdFutureInterface &fi) AndroidSdkManager::OperationOutput result; result.type = AndroidSdkManager::LicenseWorkflow; QtcProcess licenseCommand; + licenseCommand.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(m_config)); bool reviewingLicenses = false; licenseCommand.setCommand(m_config.sdkManagerToolPath().toString(), {"--licenses"}); if (Utils::HostOsInfo::isWindowsHost()) @@ -987,7 +988,7 @@ void AndroidSdkManagerPrivate::parseCommonArguments(QFutureInterface &f { QString argumentDetails; QString output; - sdkManagerCommand(m_config.sdkManagerToolPath(), QStringList("--help"), &output); + sdkManagerCommand(m_config, QStringList("--help"), &output); bool foundTag = false; for (const QString& line : output.split('\n')) { if (fi.isCanceled()) diff --git a/src/plugins/android/androidsdkmanagerwidget.cpp b/src/plugins/android/androidsdkmanagerwidget.cpp index 7ffa294e318..11877efdfe8 100644 --- a/src/plugins/android/androidsdkmanagerwidget.cpp +++ b/src/plugins/android/androidsdkmanagerwidget.cpp @@ -323,7 +323,6 @@ void AndroidSdkManagerWidget::addPackageFuture(const QFuture; - m_currentOperation->setFuture(future); connect(m_currentOperation, &QFutureWatcher::resultReadyAt, this, &AndroidSdkManagerWidget::onOperationResult); @@ -334,6 +333,7 @@ void AndroidSdkManagerWidget::addPackageFuture(const QFutureoperationProgress->setValue(value); }); + m_currentOperation->setFuture(future); } else { qCDebug(androidSdkMgrUiLog) << "Operation canceled/finished before adding to the queue"; if (m_sdkManager->isBusy()) { diff --git a/src/plugins/android/androidtoolmanager.cpp b/src/plugins/android/androidtoolmanager.cpp index fc214ab1139..c50124ce2c4 100644 --- a/src/plugins/android/androidtoolmanager.cpp +++ b/src/plugins/android/androidtoolmanager.cpp @@ -58,11 +58,11 @@ public: output. */ static bool androidToolCommand(Utils::FileName toolPath, const QStringList &args, - const Environment &environment, QString *output) + const QProcessEnvironment &environment, QString *output) { QString androidToolPath = toolPath.toString(); SynchronousProcess proc; - proc.setProcessEnvironment(environment.toProcessEnvironment()); + proc.setProcessEnvironment(environment); SynchronousProcessResponse response = proc.runBlocking(androidToolPath, args); if (response.result == SynchronousProcessResponse::Finished) { if (output) @@ -103,7 +103,7 @@ SdkPlatformList AndroidToolManager::availableSdkPlatforms(bool *ok) const SdkPlatformList list; QString targetListing; if (androidToolCommand(m_config.androidToolPath(), QStringList({"list", "target"}), - androidToolEnvironment(), &targetListing)) { + AndroidConfigurations::toolsEnvironment(m_config), &targetListing)) { m_parser->parseTargetListing(targetListing, m_config.sdkLocation(), list); success = true; } else { @@ -124,14 +124,15 @@ void AndroidToolManager::launchAvdManager() const QFuture AndroidToolManager::createAvd(CreateAvdInfo info) const { return Utils::runAsync(&AndroidToolManager::createAvdImpl, info, - m_config.androidToolPath(), androidToolEnvironment()); + m_config.androidToolPath(), + AndroidConfigurations::toolsEnvironment(m_config)); } bool AndroidToolManager::removeAvd(const QString &name) const { SynchronousProcess proc; proc.setTimeoutS(5); - proc.setProcessEnvironment(androidToolEnvironment().toProcessEnvironment()); + proc.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(m_config)); SynchronousProcessResponse response = proc.runBlocking(m_config.androidToolPath().toString(), QStringList({"delete", "avd", "-n", name})); @@ -142,27 +143,14 @@ QFuture AndroidToolManager::androidVirtualDevicesFuture() { return Utils::runAsync(&AndroidToolManager::androidVirtualDevices, m_config.androidToolPath(), m_config.sdkLocation(), - androidToolEnvironment()); -} - -Environment AndroidToolManager::androidToolEnvironment() const -{ - Environment env = Environment::systemEnvironment(); - Utils::FileName jdkLocation = m_config.openJDKLocation(); - if (!jdkLocation.isEmpty()) { - env.set(QLatin1String("JAVA_HOME"), jdkLocation.toUserOutput()); - Utils::FileName binPath = jdkLocation; - binPath.appendPath(QLatin1String("bin")); - env.prependOrSetPath(binPath.toUserOutput()); - } - return env; + AndroidConfigurations::toolsEnvironment(m_config)); } CreateAvdInfo AndroidToolManager::createAvdImpl(CreateAvdInfo info, FileName androidToolPath, - Environment env) + QProcessEnvironment env) { QProcess proc; - proc.setProcessEnvironment(env.toProcessEnvironment()); + proc.setProcessEnvironment(env); QStringList arguments; arguments << QLatin1String("create") << QLatin1String("avd") << QLatin1String("-t") << AndroidConfig::apiLevelNameFor(info.sdkPlatform) @@ -212,11 +200,11 @@ CreateAvdInfo AndroidToolManager::createAvdImpl(CreateAvdInfo info, FileName and AndroidDeviceInfoList AndroidToolManager::androidVirtualDevices(const Utils::FileName &androidTool, const FileName &sdkLocationPath, - const Environment &environment) + const QProcessEnvironment &env) { AndroidDeviceInfoList devices; QString output; - if (!androidToolCommand(androidTool, QStringList({"list", "avd"}), environment, &output)) + if (!androidToolCommand(androidTool, QStringList({"list", "avd"}), env, &output)) return devices; QStringList avds = output.split('\n'); diff --git a/src/plugins/android/androidtoolmanager.h b/src/plugins/android/androidtoolmanager.h index 61f7018bf92..0e2fb5bc400 100644 --- a/src/plugins/android/androidtoolmanager.h +++ b/src/plugins/android/androidtoolmanager.h @@ -57,12 +57,11 @@ public: // Helper methods private: - Utils::Environment androidToolEnvironment() const; static CreateAvdInfo createAvdImpl(CreateAvdInfo info, Utils::FileName androidToolPath, - Utils::Environment env); + QProcessEnvironment env); static AndroidDeviceInfoList androidVirtualDevices(const Utils::FileName &androidTool, const Utils::FileName &sdkLlocationPath, - const Utils::Environment &environment); + const QProcessEnvironment &env); private: const AndroidConfig &m_config; std::unique_ptr m_parser; diff --git a/src/plugins/beautifier/uncrustify/uncrustify.cpp b/src/plugins/beautifier/uncrustify/uncrustify.cpp index b47672bc5e0..0f00d5fc698 100644 --- a/src/plugins/beautifier/uncrustify/uncrustify.cpp +++ b/src/plugins/beautifier/uncrustify/uncrustify.cpp @@ -138,10 +138,13 @@ void Uncrustify::formatSelectedText() if (tc.hasSelection()) { // Extend selection to full lines const int posSelectionEnd = tc.selectionEnd(); + tc.setPosition(tc.selectionStart()); tc.movePosition(QTextCursor::StartOfLine); const int startPos = tc.position(); tc.setPosition(posSelectionEnd); - tc.movePosition(QTextCursor::EndOfLine); + // Don't extend the selection if the cursor is at the start of the line + if (tc.positionInBlock() > 0) + tc.movePosition(QTextCursor::EndOfLine); const int endPos = tc.position(); m_beautifierPlugin->formatCurrentFile(command(cfgFileName, true), startPos, endPos); } else if (m_settings->formatEntireFileFallback()) { diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index f2cdc4750d1..c72ab5c9e8c 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -1758,7 +1758,8 @@ bool GitClient::cleanList(const QString &workingDirectory, const QString &module const QString directory = workingDirectory + '/' + modulePath; const QStringList arguments = {"clean", "--dry-run", flag}; - const SynchronousProcessResponse resp = vcsFullySynchronousExec(directory, arguments); + const SynchronousProcessResponse resp = vcsFullySynchronousExec(directory, arguments, + VcsCommand::ForceCLocale); if (resp.result != SynchronousProcessResponse::Finished) { msgCannotRun(arguments, directory, resp.stdErr(), errorMessage); return false; @@ -2995,7 +2996,8 @@ bool GitClient::synchronousStashList(const QString &workingDirectory, QListclear(); const QStringList arguments = {"stash", "list", noColorOption}; - const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, arguments); + const SynchronousProcessResponse resp = vcsFullySynchronousExec(workingDirectory, arguments, + VcsCommand::ForceCLocale); if (resp.result != SynchronousProcessResponse::Finished) { msgCannotRun(arguments, workingDirectory, resp.stdErr(), errorMessage); return false; diff --git a/src/plugins/git/mergetool.cpp b/src/plugins/git/mergetool.cpp index 58b19b02f8a..84cfea4dd12 100644 --- a/src/plugins/git/mergetool.cpp +++ b/src/plugins/git/mergetool.cpp @@ -54,8 +54,12 @@ bool MergeTool::start(const QString &workingDirectory, const QStringList &files) { QStringList arguments; arguments << "mergetool" << "-y" << files; + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("LANG", "C"); + env.insert("LANGUAGE", "C"); m_process = new QProcess(this); m_process->setWorkingDirectory(workingDirectory); + m_process->setProcessEnvironment(env); const Utils::FileName binary = GitPlugin::client()->vcsBinary(); VcsOutputWindow::appendCommand(workingDirectory, binary, arguments); m_process->start(binary.toString(), arguments); diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 4a003ba0283..9e0150a58cc 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -324,19 +324,26 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev) const bool hasCurrentItem = current.isValid(); QAction *actionOpenFile = nullptr; QAction *actionOpenProjects = nullptr; + QAction *actionOpenAsProject = nullptr; + const Utils::FileName filePath = hasCurrentItem ? Utils::FileName::fromString( + m_fileSystemModel->filePath(current)) + : Utils::FileName(); if (hasCurrentItem) { const QString fileName = m_fileSystemModel->fileName(current); - if (m_fileSystemModel->isDir(current)) + if (m_fileSystemModel->isDir(current)) { actionOpenProjects = menu.addAction(tr("Open Project in \"%1\"").arg(fileName)); - else + } else { actionOpenFile = menu.addAction(tr("Open \"%1\"").arg(fileName)); + if (ProjectExplorerPlugin::isProjectFile(Utils::FileName::fromString(fileName))) + actionOpenAsProject = menu.addAction(tr("Open Project \"%1\"").arg(fileName)); + } } // we need dummy DocumentModel::Entry with absolute file path in it // to get EditorManager::addNativeDirAndOpenWithActions() working Core::DocumentModel::Entry fakeEntry; Core::IDocument document; - document.setFilePath(Utils::FileName::fromString(m_fileSystemModel->filePath(current))); + document.setFilePath(filePath); fakeEntry.document = &document; Core::EditorManager::addNativeDirAndOpenWithActions(&menu, &fakeEntry); @@ -347,6 +354,8 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev) ev->accept(); if (action == actionOpenFile) openItem(current); + else if (action == actionOpenAsProject) + ProjectExplorerPlugin::openProject(filePath.toString()); else if (action == actionOpenProjects) openProjectsInDirectory(current); } diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 6ec591b6ab0..679214925b3 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -3530,6 +3530,16 @@ QStringList ProjectExplorerPlugin::projectFilePatterns() return patterns; } +bool ProjectExplorerPlugin::isProjectFile(const Utils::FileName &filePath) +{ + Utils::MimeType mt = Utils::mimeTypeForFile(filePath.toString()); + for (const QString &mime : dd->m_projectCreators.keys()) { + if (mt.inherits(mime)) + return true; + } + return false; +} + void ProjectExplorerPlugin::openOpenProjectDialog() { const QString path = DocumentManager::useProjectsDirectory() diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 2ffb0d200d0..39cd4e736b3 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -43,7 +43,10 @@ class IMode; class Id; } // namespace Core -namespace Utils { class ProcessHandle; } +namespace Utils { +class ProcessHandle; +class FileName; +} namespace ProjectExplorer { class RunControl; @@ -132,6 +135,7 @@ public: // internal public for FlatModel static void renameFile(Node *node, const QString &newFilePath); static QStringList projectFilePatterns(); + static bool isProjectFile(const Utils::FileName &filePath); static QList > recentProjects(); static bool canRunStartupProject(Core::Id runMode, QString *whyNot = nullptr); diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index acc3e312ad1..ddb85144eae 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -786,8 +786,10 @@ void VcsBasePlugin::setProcessEnvironment(QProcessEnvironment *e, bool forceCLocale, const QString &sshPromptBinary) { - if (forceCLocale) + if (forceCLocale) { e->insert("LANG", "C"); + e->insert("LANGUAGE", "C"); + } if (!sshPromptBinary.isEmpty()) e->insert("SSH_ASKPASS", sshPromptBinary); }