Merge remote-tracking branch 'origin/master' into 4.11

Change-Id: I039c82e198863e8506723c9fb7a37ca51260afd3
This commit is contained in:
Eike Ziller
2019-09-26 15:25:44 +02:00
27 changed files with 385 additions and 150 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -52,7 +52,11 @@
code and translations. The lrelease tool is used to create run-time
translation files for use by the released application.
To synchronize translation source (TS) files from a translator with the
When you \l{Creating Projects}{create a new project}, you can automatically
generate a translation source file (TS) for one language. You can add other
languages later by editing the project file.
To synchronize TS files from a translator with the
application code, select \uicontrol Tools > \uicontrol External >
\uicontrol Linguist > \uicontrol {Update Translations (lupdate)}.

View File

@@ -104,8 +104,8 @@
applications in WebAssembly format, to deploy them, and to
run them in a web browser.
\li \l{http://doc.qt.io/qtcreator/creator-overview-qtasam.html}
{Qt Application Manager}
\li \l{https://doc.qt.io/qtcreator/creator-overview-qtasam.html}
{Qt Creator Plugin for Qt Application Manager}
You can use the experimental Qt Application Manager plugin
(commercial only) to deploy, run, and debug applications on the

View File

@@ -128,6 +128,16 @@
\li Select \uicontrol Next.
\li In the \uicontrol Language field, select a language that you plan
to \l {Using Qt Linguist}{translate} the application to. You can
add other languages later by editing the project file.
\li In the \uicontrol {Translation file} field, you can edit the
name for the translation source file that will be generated
for the selected language.
\li Select \uicontrol Next.
\li Select \l{glossary-buildandrun-kit}{kits} for running and building
your project, and then click \uicontrol Next.

View File

@@ -181,6 +181,12 @@
For more information, see
\l {Internationalization and Localization with Qt Quick}.
\if defined(qtcreator)
When you \l{Creating Qt Quick Projects}{create a new project}, you can
automatically generate a translation source file (TS) for one language.
You can add other languages later by editing the project file.
\endif
\section1 Loading Placeholder Data
The Design mode supports views, models, and delegates, so that when you add

View File

@@ -52,7 +52,6 @@ add_subdirectory(genericprojectmanager)
add_subdirectory(git)
add_subdirectory(mercurial)
add_subdirectory(perforce)
add_subdirectory(python)
add_subdirectory(qmakeprojectmanager)
add_subdirectory(qmljstools)
add_subdirectory(qmlprojectmanager)
@@ -70,6 +69,7 @@ add_subdirectory(baremetal)
add_subdirectory(clangcodemodel)
add_subdirectory(clangtools)
add_subdirectory(ios)
add_subdirectory(python)
add_subdirectory(qmljseditor)
add_subdirectory(qmlpreview)
add_subdirectory(qmlprofiler)

View File

@@ -36,7 +36,6 @@
#include <functional>
QT_BEGIN_NAMESPACE
class QMessageBox;
class QWidget;
class QMenu;
class QAction;
@@ -50,9 +49,6 @@ class SavedAction;
namespace Debugger {
namespace Internal {
class Console;
class Symbol;
class Section;
class GlobalDebuggerOptions;
enum TestCases
@@ -64,23 +60,16 @@ enum TestCases
// Some convenience.
void openTextEditor(const QString &titlePattern, const QString &contents);
void showModuleSymbols(const QString &moduleName, const QVector<Internal::Symbol> &symbols);
void showModuleSections(const QString &moduleName, const QVector<Internal::Section> &sections);
QSharedPointer<Internal::GlobalDebuggerOptions> globalDebuggerOptions();
bool isTestRun();
Utils::SavedAction *action(int code);
Console *console();
bool boolSetting(int code);
QString stringSetting(int code);
QStringList stringListSetting(int code);
QMessageBox *showMessageBox(int icon, const QString &title,
const QString &text, int buttons = 0);
QAction *addAction(QMenu *menu, const QString &display, bool on,
const std::function<void()> &onTriggered = {});
QAction *addAction(QMenu *menu, const QString &d1, const QString &d2, bool on,

View File

@@ -2619,6 +2619,73 @@ QString DebuggerEngine::formatStartParameters() const
return rc;
}
static void createNewDock(QWidget *widget)
{
auto dockWidget = new QDockWidget;
dockWidget->setWidget(widget);
dockWidget->setWindowTitle(widget->windowTitle());
dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
dockWidget->show();
}
void DebuggerEngine::showModuleSymbols(const QString &moduleName, const Symbols &symbols)
{
auto w = new QTreeWidget;
w->setUniformRowHeights(true);
w->setColumnCount(5);
w->setRootIsDecorated(false);
w->setAlternatingRowColors(true);
w->setSortingEnabled(true);
w->setObjectName("Symbols." + moduleName);
QStringList header;
header.append(tr("Symbol"));
header.append(tr("Address"));
header.append(tr("Code"));
header.append(tr("Section"));
header.append(tr("Name"));
w->setHeaderLabels(header);
w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
for (const Symbol &s : symbols) {
auto it = new QTreeWidgetItem;
it->setData(0, Qt::DisplayRole, s.name);
it->setData(1, Qt::DisplayRole, s.address);
it->setData(2, Qt::DisplayRole, s.state);
it->setData(3, Qt::DisplayRole, s.section);
it->setData(4, Qt::DisplayRole, s.demangled);
w->addTopLevelItem(it);
}
createNewDock(w);
}
void DebuggerEngine::showModuleSections(const QString &moduleName, const Sections &sections)
{
auto w = new QTreeWidget;
w->setUniformRowHeights(true);
w->setColumnCount(5);
w->setRootIsDecorated(false);
w->setAlternatingRowColors(true);
w->setSortingEnabled(true);
w->setObjectName("Sections." + moduleName);
QStringList header;
header.append(tr("Name"));
header.append(tr("From"));
header.append(tr("To"));
header.append(tr("Address"));
header.append(tr("Flags"));
w->setHeaderLabels(header);
w->setWindowTitle(tr("Sections in \"%1\"").arg(moduleName));
for (const Section &s : sections) {
auto it = new QTreeWidgetItem;
it->setData(0, Qt::DisplayRole, s.name);
it->setData(1, Qt::DisplayRole, s.from);
it->setData(2, Qt::DisplayRole, s.to);
it->setData(3, Qt::DisplayRole, s.address);
it->setData(4, Qt::DisplayRole, s.flags);
w->addTopLevelItem(it);
}
createNewDock(w);
}
// CppDebuggerEngine
Context CppDebuggerEngine::languageContext() const

View File

@@ -102,9 +102,11 @@ class LogWindow;
class ModulesHandler;
class RegisterHandler;
class PeripheralRegisterHandler;
class StackHandler;
class StackFrame;
class Section;
class SourceFilesHandler;
class StackFrame;
class StackHandler;
class Symbol;
class WatchHandler;
class WatchTreeView;
class DebuggerToolTipContext;
@@ -460,6 +462,9 @@ public:
void openMemoryEditor();
static void showModuleSymbols(const QString &moduleName, const QVector<Symbol> &symbols);
static void showModuleSections(const QString &moduleName, const QVector<Section> &sections);
void handleExecDetach();
void handleExecContinue();
void handleExecInterrupt();
@@ -546,7 +551,6 @@ protected:
bool isNativeMixedActiveFrame() const;
void startDying() const;
protected:
ProjectExplorer::IDevice::ConstPtr device() const;
DebuggerEngine *companionEngine() const;

View File

@@ -2015,15 +2015,6 @@ void DebuggerPluginPrivate::aboutToShutdown()
m_shutdownTimer.start();
}
static void createNewDock(QWidget *widget)
{
auto dockWidget = new QDockWidget;
dockWidget->setWidget(widget);
dockWidget->setWindowTitle(widget->windowTitle());
dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
dockWidget->show();
}
void DebuggerPluginPrivate::remoteCommand(const QStringList &options)
{
if (options.isEmpty())
@@ -2038,17 +2029,6 @@ void DebuggerPluginPrivate::remoteCommand(const QStringList &options)
runScheduled();
}
QMessageBox *showMessageBox(int icon, const QString &title, const QString &text, int buttons)
{
QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon),
title, text, QMessageBox::StandardButtons(buttons),
ICore::mainWindow());
mb->setAttribute(Qt::WA_DeleteOnClose);
mb->setTextInteractionFlags(Qt::TextSelectableByMouse);
mb->show();
return mb;
}
void addDebugInfoTask(unsigned id, const QString &cmd)
{
dd->m_debugInfoTaskHandler.addTask(id, cmd);
@@ -2117,64 +2097,6 @@ QStringList stringListSetting(int code)
return action(code)->value().toStringList();
}
void showModuleSymbols(const QString &moduleName, const Symbols &symbols)
{
auto w = new QTreeWidget;
w->setUniformRowHeights(true);
w->setColumnCount(5);
w->setRootIsDecorated(false);
w->setAlternatingRowColors(true);
w->setSortingEnabled(true);
w->setObjectName("Symbols." + moduleName);
QStringList header;
header.append(DebuggerPlugin::tr("Symbol"));
header.append(DebuggerPlugin::tr("Address"));
header.append(DebuggerPlugin::tr("Code"));
header.append(DebuggerPlugin::tr("Section"));
header.append(DebuggerPlugin::tr("Name"));
w->setHeaderLabels(header);
w->setWindowTitle(DebuggerPlugin::tr("Symbols in \"%1\"").arg(moduleName));
for (const Symbol &s : symbols) {
auto it = new QTreeWidgetItem;
it->setData(0, Qt::DisplayRole, s.name);
it->setData(1, Qt::DisplayRole, s.address);
it->setData(2, Qt::DisplayRole, s.state);
it->setData(3, Qt::DisplayRole, s.section);
it->setData(4, Qt::DisplayRole, s.demangled);
w->addTopLevelItem(it);
}
createNewDock(w);
}
void showModuleSections(const QString &moduleName, const Sections &sections)
{
auto w = new QTreeWidget;
w->setUniformRowHeights(true);
w->setColumnCount(5);
w->setRootIsDecorated(false);
w->setAlternatingRowColors(true);
w->setSortingEnabled(true);
w->setObjectName("Sections." + moduleName);
QStringList header;
header.append(DebuggerPlugin::tr("Name"));
header.append(DebuggerPlugin::tr("From"));
header.append(DebuggerPlugin::tr("To"));
header.append(DebuggerPlugin::tr("Address"));
header.append(DebuggerPlugin::tr("Flags"));
w->setHeaderLabels(header);
w->setWindowTitle(DebuggerPlugin::tr("Sections in \"%1\"").arg(moduleName));
for (const Section &s : sections) {
auto it = new QTreeWidgetItem;
it->setData(0, Qt::DisplayRole, s.name);
it->setData(1, Qt::DisplayRole, s.from);
it->setData(2, Qt::DisplayRole, s.to);
it->setData(3, Qt::DisplayRole, s.address);
it->setData(4, Qt::DisplayRole, s.flags);
w->addTopLevelItem(it);
}
createNewDock(w);
}
void openTextEditor(const QString &titlePattern0, const QString &contents)
{
if (dd->m_shuttingDown)

View File

@@ -103,6 +103,17 @@ static bool isMostlyHarmlessMessage(const QStringRef &msg)
"Invalid argument\\n";
}
static QMessageBox *showMessageBox(QMessageBox::Icon icon,
const QString &title, const QString &text,
QMessageBox::StandardButtons buttons)
{
auto mb = new QMessageBox(icon, title, text, buttons, ICore::mainWindow());
mb->setAttribute(Qt::WA_DeleteOnClose);
mb->setTextInteractionFlags(Qt::TextSelectableByMouse);
mb->show();
return mb;
}
///////////////////////////////////////////////////////////////////////
//
// GdbEngine
@@ -2651,7 +2662,7 @@ static void handleShowModuleSymbols(const DebuggerResponse &response,
}
file.close();
file.remove();
Internal::showModuleSymbols(modulePath, symbols);
DebuggerEngine::showModuleSymbols(modulePath, symbols);
} else {
AsynchronousMessageBox::critical(GdbEngine::tr("Cannot Read Symbols"),
GdbEngine::tr("Cannot read symbols for module \"%1\".").arg(fileName));
@@ -2716,7 +2727,7 @@ void GdbEngine::handleShowModuleSections(const DebuggerResponse &response,
}
}
if (!sections.isEmpty())
Internal::showModuleSections(moduleName, sections);
DebuggerEngine::showModuleSections(moduleName, sections);
}
}

View File

@@ -669,7 +669,7 @@ void LldbEngine::requestModuleSymbols(const QString &moduleName)
{
DebuggerCommand cmd("fetchSymbols");
cmd.arg("module", moduleName);
cmd.callback = [moduleName](const DebuggerResponse &response) {
cmd.callback = [this, moduleName](const DebuggerResponse &response) {
const GdbMi &symbols = response.data["symbols"];
QString moduleName = response.data["module"].data();
Symbols syms;
@@ -682,7 +682,7 @@ void LldbEngine::requestModuleSymbols(const QString &moduleName)
symbol.demangled = item["demangled"].data();
syms.append(symbol);
}
Internal::showModuleSymbols(moduleName, syms);
showModuleSymbols(moduleName, syms);
};
runCommand(cmd);
}

View File

@@ -369,7 +369,7 @@ void PdbEngine::refreshSymbols(const GdbMi &symbols)
symbol.name = item["name"].data();
syms.append(symbol);
}
Internal::showModuleSymbols(moduleName, syms);
showModuleSymbols(moduleName, syms);
}
bool PdbEngine::canHandleToolTip(const DebuggerToolTipContext &) const

View File

@@ -161,7 +161,7 @@ static void blockRecursion(const Overview &overview,
// Go backwards in case someone has identical variables in the same scope.
// Fixme: loop variables or similar are currently seen in the outer scope
for (int s = scope->memberCount() - 1; s >= 0; --s){
const Symbol *symbol = scope->memberAt(s);
const CPlusPlus::Symbol *symbol = scope->memberAt(s);
if (symbol->isDeclaration()) {
// Find out about shadowed symbols by bookkeeping
// the already seen occurrences in a hash.
@@ -197,7 +197,7 @@ QStringList getUninitializedVariables(const Snapshot &snapshot,
const Document::Ptr doc = docIt.value();
// Look at symbol at line and find its function. Either it is the
// function itself or some expression/variable.
const Symbol *symbolAtLine = doc->lastVisibleSymbolAt(line, 0);
const CPlusPlus::Symbol *symbolAtLine = doc->lastVisibleSymbolAt(line, 0);
if (!symbolAtLine)
return result;
// First figure out the function to do a safety name check

View File

@@ -4,19 +4,17 @@ project(QLiteHtml)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/litehtml/CMakeLists.txt)
set(ORIG_FPIC ${CMAKE_POSITION_INDEPENDENT_CODE})
set(ORIG_CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE})
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
else()
set(CMAKE_BUILD_TYPE "Release")
endif()
if (WIN32)
set(LITEHTML_UTF8 ON)
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(litehtml)
set(CMAKE_BUILD_TYPE ${ORIG_CMAKE_BUILD_TYPE})
set(CMAKE_POSITION_INDEPENDENT_CODE "${ORIG_FPIC}")
# force optimized litehtml even in debug
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(gumbo PRIVATE -O2)
target_compile_options(litehtml PRIVATE -O2)
endif()
else()
find_package(litehtml REQUIRED)
endif()

View File

@@ -652,11 +652,9 @@ void DocumentContainer::buildIndex()
void DocumentContainer::draw_background(litehtml::uint_ptr hdc, const litehtml::background_paint &bg)
{
// TODO
auto painter = toQPainter(hdc);
if (bg.is_root) {
// TODO ?
drawSelection(painter, toQRect(bg.border_box));
return;
}
painter->save();
@@ -935,6 +933,14 @@ void DocumentContainer::render(int width, int height)
m_selection.update();
}
void DocumentContainer::draw(QPainter *painter, const QRect &clip)
{
drawSelection(painter, clip);
const QPoint pos = -m_scrollPosition;
const litehtml::position clipRect = {clip.x(), clip.y(), clip.width(), clip.height()};
document()->draw(reinterpret_cast<litehtml::uint_ptr>(painter), pos.x(), pos.y(), &clipRect);
}
QVector<QRect> DocumentContainer::mousePressEvent(const QPoint &documentPos,
const QPoint &viewportPos,
Qt::MouseButton button)

View File

@@ -143,6 +143,7 @@ public: // outside API
litehtml::document::ptr document() const;
void setScrollPosition(const QPoint &pos);
void render(int width, int height);
void draw(QPainter *painter, const QRect &clip);
// these return areas to redraw in document space
QVector<QRect> mousePressEvent(const QPoint &documentPos,

View File

@@ -523,17 +523,11 @@ void QLiteHtmlWidget::paintEvent(QPaintEvent *event)
if (!d->documentContainer.document())
return;
d->documentContainer.setScrollPosition(scrollPosition());
const QPoint pos = -scrollPosition();
const QRect r = toVirtual(event->rect());
const litehtml::position clip = {r.x(), r.y(), r.width(), r.height()};
QPainter p(viewport());
p.setWorldTransform(QTransform().scale(d->zoomFactor, d->zoomFactor));
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
p.setRenderHint(QPainter::Antialiasing, true);
d->documentContainer.document()->draw(reinterpret_cast<litehtml::uint_ptr>(&p),
pos.x(),
pos.y(),
&clip);
d->documentContainer.draw(&p, toVirtual(event->rect()));
}
static litehtml::element::ptr elementForY(int y, const litehtml::document::ptr &document)

View File

@@ -218,18 +218,29 @@ void updateEditorToolBar(Core::IEditor *editor)
const QIcon icon = Utils::Icon({{":/languageclient/images/languageclient.png",
Utils::Theme::IconsBaseColor}})
.icon();
actions[widget] = widget->toolBar()->addAction(icon, client->name(), [document]() {
auto menu = new QMenu;
for (auto client : LanguageClientManager::clientsSupportingDocument(document))
menu->addAction(client->name(), [client = QPointer<Client>(client), document]() {
if (client)
actions[widget] = widget->toolBar()->addAction(
icon, client->name(), [document]() {
auto menu = new QMenu;
auto *clientsGroup = new QActionGroup(menu);
clientsGroup->setExclusive(true);
for (auto client : LanguageClientManager::clientsSupportingDocument(document)) {
auto action = clientsGroup->addAction(client->name());
auto reopen = [action, client = QPointer<Client>(client), document]() {
if (!client)
return;
LanguageClientManager::reOpenDocumentWithClient(document, client);
action->setChecked(true);
};
action->setCheckable(true);
action->setChecked(client == LanguageClientManager::clientForDocument(document));
QObject::connect(action, &QAction::triggered, reopen);
}
menu->addActions(clientsGroup->actions());
menu->addAction("Manage...", []() {
Core::ICore::showOptionsDialog(Constants::LANGUAGECLIENT_SETTINGS_PAGE);
});
menu->addAction("Manage...", []() {
Core::ICore::showOptionsDialog(Constants::LANGUAGECLIENT_SETTINGS_PAGE);
menu->popup(QCursor::pos());
});
menu->popup(QCursor::pos());
});
QObject::connect(widget, &QWidget::destroyed, [widget]() {
actions.remove(widget);
});

View File

@@ -996,7 +996,7 @@ QList<ToolChain *> GccToolChainFactory::autoDetect(const QList<ToolChain *> &alr
QList<ToolChain *> GccToolChainFactory::detectForImport(const ToolChainDescription &tcd)
{
const QString fileName = tcd.compilerPath.toString();
const QString fileName = tcd.compilerPath.toFileInfo().completeBaseName();
if ((tcd.language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|| fileName.endsWith("gcc")))
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")
@@ -1764,7 +1764,7 @@ QList<ToolChain *> MingwToolChainFactory::autoDetect(const QList<ToolChain *> &a
QList<ToolChain *> MingwToolChainFactory::detectForImport(const ToolChainDescription &tcd)
{
const QString fileName = tcd.compilerPath.toString();
const QString fileName = tcd.compilerPath.toFileInfo().completeBaseName();
if ((tcd.language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|| fileName.endsWith("gcc")))
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")

View File

@@ -1,5 +1,5 @@
add_qtc_plugin(Python
PLUGIN_DEPENDS Core ProjectExplorer TextEditor
PLUGIN_DEPENDS Core LanguageClient ProjectExplorer TextEditor
SOURCES
python.qrc
pythoneditor.cpp pythoneditor.h

View File

@@ -9,6 +9,7 @@ QtcPlugin {
Depends { name: "Core" }
Depends { name: "TextEditor" }
Depends { name: "ProjectExplorer" }
Depends { name: "LanguageClient" }
Group {
name: "General"

View File

@@ -4,5 +4,6 @@ QTC_LIB_DEPENDS += \
utils
QTC_PLUGIN_DEPENDS += \
coreplugin \
texteditor \
projectexplorer
languageclient \
projectexplorer \
texteditor

View File

@@ -25,40 +25,241 @@
#include "pythoneditor.h"
#include "pythonconstants.h"
#include "pythonplugin.h"
#include "pythonindenter.h"
#include "pythonhighlighter.h"
#include "pythonindenter.h"
#include "pythonplugin.h"
#include "pythonproject.h"
#include "pythonrunconfiguration.h"
#include "pythonsettings.h"
#include <coreplugin/infobar.h>
#include <languageclient/client.h>
#include <languageclient/languageclientinterface.h>
#include <languageclient/languageclientmanager.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorconstants.h>
#include <texteditor/textdocument.h>
#include <utils/qtcassert.h>
#include <utils/synchronousprocess.h>
#include <QCoreApplication>
#include <QRegularExpression>
using namespace TextEditor;
using namespace ProjectExplorer;
using namespace Utils;
namespace Python {
namespace Internal {
static constexpr char startPylsInfoBarId[] = "PythonEditor::StartPyls";
struct PythonForProject
{
FilePath path;
PythonProject *project = nullptr;
QString name() const
{
if (!path.exists())
return {};
if (cachedName.first != path) {
SynchronousProcess pythonProcess;
const CommandLine pythonVersionCommand(path, {"--version"});
SynchronousProcessResponse response = pythonProcess.runBlocking(pythonVersionCommand);
cachedName.first = path;
cachedName.second = response.allOutput().trimmed();
}
return cachedName.second;
}
private:
mutable QPair<FilePath, QString> cachedName;
};
static PythonForProject detectPython(TextEditor::TextDocument *document)
{
PythonForProject python;
python.project = qobject_cast<PythonProject *>(
SessionManager::projectForFile(document->filePath()));
if (!python.project)
python.project = qobject_cast<PythonProject *>(SessionManager::startupProject());
if (python.project) {
if (auto target = python.project->activeTarget()) {
if (auto runConfig = qobject_cast<PythonRunConfiguration *>(
target->activeRunConfiguration())) {
python.path = FilePath::fromString(runConfig->interpreter());
}
}
}
if (!python.path.exists())
python.path = PythonSettings::defaultInterpreter().command;
if (!python.path.exists() && !PythonSettings::interpreters().isEmpty())
python.path = PythonSettings::interpreters().first().command;
return python;
}
FilePath getPylsModulePath(CommandLine pylsCommand)
{
pylsCommand.addArg("-h");
SynchronousProcess pythonProcess;
pythonProcess.setEnvironment(pythonProcess.environment() + QStringList("PYTHONVERBOSE=x"));
SynchronousProcessResponse response = pythonProcess.runBlocking(pylsCommand);
static const QString pylsInitPattern = "(.*)"
+ QRegularExpression::escape(
QDir::toNativeSeparators("/pyls/__init__.py"))
+ '$';
static const QString cachedPattern = " matches " + pylsInitPattern;
static const QRegularExpression regexCached(" matches " + pylsInitPattern,
QRegularExpression::MultilineOption);
static const QRegularExpression regexNotCached(" code object from " + pylsInitPattern,
QRegularExpression::MultilineOption);
const QString &output = response.allOutput();
for (auto regex : {regexCached, regexNotCached}) {
QRegularExpressionMatch result = regex.match(output);
if (result.hasMatch())
return FilePath::fromUserInput(result.captured(1));
}
return {};
}
struct PythonLanguageServerState
{
enum { CanNotBeInstalled, CanBeInstalled, AlreadyInstalled, AlreadyConfigured } state;
FilePath pylsModulePath;
};
static QList<const LanguageClient::StdIOSettings *> configuredPythonLanguageServer(
Core::IDocument *doc)
{
using namespace LanguageClient;
QList<const StdIOSettings *> result;
for (const BaseSettings *setting : LanguageClientManager::currentSettings()) {
if (setting->m_languageFilter.isSupported(doc))
result << dynamic_cast<const StdIOSettings *>(setting);
}
return result;
}
static PythonLanguageServerState checkPythonLanguageServer(const FilePath &python,
TextEditor::TextDocument *document)
{
using namespace LanguageClient;
SynchronousProcess pythonProcess;
const CommandLine pythonLShelpCommand(python, {"-m", "pyls", "-h"});
SynchronousProcessResponse response = pythonProcess.runBlocking(pythonLShelpCommand);
if (response.allOutput().contains("Python Language Server")) {
const FilePath &modulePath = getPylsModulePath(pythonLShelpCommand);
for (const StdIOSettings *serverSetting : configuredPythonLanguageServer(document)) {
CommandLine serverCommand(FilePath::fromUserInput(serverSetting->m_executable),
serverSetting->arguments(),
CommandLine::Raw);
if (modulePath == getPylsModulePath(serverCommand))
return {PythonLanguageServerState::AlreadyConfigured, FilePath()};
}
return {PythonLanguageServerState::AlreadyInstalled, getPylsModulePath(pythonLShelpCommand)};
}
const CommandLine pythonPipVersionCommand(python, {"-m", "pip", "-V"});
response = pythonProcess.runBlocking(pythonPipVersionCommand);
if (response.allOutput().startsWith("pip "))
return {PythonLanguageServerState::CanBeInstalled, FilePath()};
else
return {PythonLanguageServerState::CanNotBeInstalled, FilePath()};
}
static LanguageClient::Client *registerLanguageServer(const PythonForProject &python)
{
auto *settings = new LanguageClient::StdIOSettings();
settings->m_executable = python.path.toString();
settings->m_arguments = "-m pyls";
settings->m_name = PythonEditorFactory::tr("Python Language Server (%1)").arg(python.name());
settings->m_languageFilter.mimeTypes = QStringList(Constants::C_PY_MIMETYPE);
LanguageClient::LanguageClientManager::registerClientSettings(settings);
return LanguageClient::LanguageClientManager::clientForSetting(settings).value(0);
}
static void setupPythonLanguageServer(const PythonForProject &python,
QPointer<TextEditor::TextDocument> document)
{
document->infoBar()->removeInfo(startPylsInfoBarId);
if (LanguageClient::Client *client = registerLanguageServer(python))
LanguageClient::LanguageClientManager::reOpenDocumentWithClient(document, client);
}
static void updateEditorInfoBar(const PythonForProject &python, TextEditor::TextDocument *document)
{
const PythonLanguageServerState &lsState = checkPythonLanguageServer(python.path, document);
if (lsState.state == PythonLanguageServerState::CanNotBeInstalled
|| lsState.state == PythonLanguageServerState::AlreadyConfigured
|| lsState.state == PythonLanguageServerState::CanBeInstalled /* TODO */) {
return;
}
Core::InfoBar *infoBar = document->infoBar();
if (lsState.state == PythonLanguageServerState::AlreadyInstalled
&& infoBar->canInfoBeAdded(startPylsInfoBarId)) {
auto message = PythonEditorFactory::tr("Found a Python language server for %1 (%2). "
"Should this one be set up for this document?")
.arg(python.name(), python.path.toUserOutput());
Core::InfoBarEntry info(startPylsInfoBarId,
message,
Core::InfoBarEntry::GlobalSuppression::Enabled);
info.setCustomButtonInfo(TextEditor::BaseTextEditor::tr("Setup"),
[=]() { setupPythonLanguageServer(python, document); });
infoBar->addInfo(info);
}
}
static void documentOpened(Core::IDocument *document)
{
auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
if (!textDocument || textDocument->mimeType() != Constants::C_PY_MIMETYPE)
return;
const PythonForProject &python = detectPython(textDocument);
if (!python.path.exists())
return;
updateEditorInfoBar(python, textDocument);
}
PythonEditorFactory::PythonEditorFactory()
{
setId(Constants::C_PYTHONEDITOR_ID);
setDisplayName(QCoreApplication::translate("OpenWith::Editors", Constants::C_EDITOR_DISPLAY_NAME));
setDisplayName(
QCoreApplication::translate("OpenWith::Editors", Constants::C_EDITOR_DISPLAY_NAME));
addMimeType(Constants::C_PY_MIMETYPE);
setEditorActionHandlers(TextEditorActionHandler::Format
| TextEditorActionHandler::UnCommentSelection
| TextEditorActionHandler::UnCollapseAll
| TextEditorActionHandler::FollowSymbolUnderCursor);
setEditorActionHandlers(TextEditor::TextEditorActionHandler::Format
| TextEditor::TextEditorActionHandler::UnCommentSelection
| TextEditor::TextEditorActionHandler::UnCollapseAll
| TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor);
setDocumentCreator([] { return new TextDocument(Constants::C_PYTHONEDITOR_ID); });
setDocumentCreator([] { return new TextEditor::TextDocument(Constants::C_PYTHONEDITOR_ID); });
setIndenterCreator([](QTextDocument *doc) { return new PythonIndenter(doc); });
setSyntaxHighlighterCreator([] { return new PythonHighlighter; });
setCommentDefinition(Utils::CommentDefinition::HashStyle);
setCommentDefinition(CommentDefinition::HashStyle);
setParenthesesMatchingEnabled(true);
setCodeFoldingSupported(true);
connect(Core::EditorManager::instance(), &Core::EditorManager::documentOpened,
this, documentOpened);
}
} // namespace Internal

View File

@@ -42,6 +42,7 @@ class PythonRunConfiguration : public ProjectExplorer::RunConfiguration
public:
PythonRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
QString interpreter() const;
private:
void doAdditionalSetup(const ProjectExplorer::RunConfigurationCreationInfo &) final;
@@ -49,7 +50,6 @@ private:
bool supportsDebugger() const;
QString mainScript() const;
QString arguments() const;
QString interpreter() const;
void updateTargetInformation();
};

View File

@@ -801,10 +801,19 @@ void TimelineBarItem::itemMoved(const QPointF &start, const QPointF &end)
if (isActiveHandle(Location::Undefined))
dragInit(rect(), start);
const qreal min = qreal(TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset
- scrollOffset());
const qreal max = qreal(timelineScene()->rulerWidth() - TimelineConstants::sectionWidth
+ rect().width());
qreal min = qreal(TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset
- scrollOffset());
qreal max = qreal(timelineScene()->rulerWidth() - TimelineConstants::sectionWidth
+ rect().width());
const qreal minFrameX = mapFromFrameToScene(timelineScene()->startFrame());
const qreal maxFrameX = mapFromFrameToScene(timelineScene()->endFrame());
if (min < minFrameX)
min = minFrameX;
if (max > maxFrameX)
max = maxFrameX;
if (isActiveHandle(Location::Center))
dragCenter(rect(), end, min, max);

View File

@@ -3,7 +3,7 @@ if (NOT TARGET Qt5::Designer)
endif()
add_qtc_library(designerintegrationv2 STATIC
DEPENDS Qt5::Designer
DEPENDS Qt5::Designer Qt5::Widgets
SOURCES
formresizer.cpp formresizer.h
sizehandlerect.cpp sizehandlerect.h