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 code and translations. The lrelease tool is used to create run-time
translation files for use by the released application. 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 > application code, select \uicontrol Tools > \uicontrol External >
\uicontrol Linguist > \uicontrol {Update Translations (lupdate)}. \uicontrol Linguist > \uicontrol {Update Translations (lupdate)}.

View File

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

View File

@@ -128,6 +128,16 @@
\li Select \uicontrol Next. \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 \li Select \l{glossary-buildandrun-kit}{kits} for running and building
your project, and then click \uicontrol Next. your project, and then click \uicontrol Next.

View File

@@ -181,6 +181,12 @@
For more information, see For more information, see
\l {Internationalization and Localization with Qt Quick}. \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 \section1 Loading Placeholder Data
The Design mode supports views, models, and delegates, so that when you add 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(git)
add_subdirectory(mercurial) add_subdirectory(mercurial)
add_subdirectory(perforce) add_subdirectory(perforce)
add_subdirectory(python)
add_subdirectory(qmakeprojectmanager) add_subdirectory(qmakeprojectmanager)
add_subdirectory(qmljstools) add_subdirectory(qmljstools)
add_subdirectory(qmlprojectmanager) add_subdirectory(qmlprojectmanager)
@@ -70,6 +69,7 @@ add_subdirectory(baremetal)
add_subdirectory(clangcodemodel) add_subdirectory(clangcodemodel)
add_subdirectory(clangtools) add_subdirectory(clangtools)
add_subdirectory(ios) add_subdirectory(ios)
add_subdirectory(python)
add_subdirectory(qmljseditor) add_subdirectory(qmljseditor)
add_subdirectory(qmlpreview) add_subdirectory(qmlpreview)
add_subdirectory(qmlprofiler) add_subdirectory(qmlprofiler)

View File

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

View File

@@ -2619,6 +2619,73 @@ QString DebuggerEngine::formatStartParameters() const
return rc; 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 // CppDebuggerEngine
Context CppDebuggerEngine::languageContext() const Context CppDebuggerEngine::languageContext() const

View File

@@ -102,9 +102,11 @@ class LogWindow;
class ModulesHandler; class ModulesHandler;
class RegisterHandler; class RegisterHandler;
class PeripheralRegisterHandler; class PeripheralRegisterHandler;
class StackHandler; class Section;
class StackFrame;
class SourceFilesHandler; class SourceFilesHandler;
class StackFrame;
class StackHandler;
class Symbol;
class WatchHandler; class WatchHandler;
class WatchTreeView; class WatchTreeView;
class DebuggerToolTipContext; class DebuggerToolTipContext;
@@ -460,6 +462,9 @@ public:
void openMemoryEditor(); 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 handleExecDetach();
void handleExecContinue(); void handleExecContinue();
void handleExecInterrupt(); void handleExecInterrupt();
@@ -546,7 +551,6 @@ protected:
bool isNativeMixedActiveFrame() const; bool isNativeMixedActiveFrame() const;
void startDying() const; void startDying() const;
protected:
ProjectExplorer::IDevice::ConstPtr device() const; ProjectExplorer::IDevice::ConstPtr device() const;
DebuggerEngine *companionEngine() const; DebuggerEngine *companionEngine() const;

View File

@@ -2015,15 +2015,6 @@ void DebuggerPluginPrivate::aboutToShutdown()
m_shutdownTimer.start(); 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) void DebuggerPluginPrivate::remoteCommand(const QStringList &options)
{ {
if (options.isEmpty()) if (options.isEmpty())
@@ -2038,17 +2029,6 @@ void DebuggerPluginPrivate::remoteCommand(const QStringList &options)
runScheduled(); 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) void addDebugInfoTask(unsigned id, const QString &cmd)
{ {
dd->m_debugInfoTaskHandler.addTask(id, cmd); dd->m_debugInfoTaskHandler.addTask(id, cmd);
@@ -2117,64 +2097,6 @@ QStringList stringListSetting(int code)
return action(code)->value().toStringList(); 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) void openTextEditor(const QString &titlePattern0, const QString &contents)
{ {
if (dd->m_shuttingDown) if (dd->m_shuttingDown)

View File

@@ -103,6 +103,17 @@ static bool isMostlyHarmlessMessage(const QStringRef &msg)
"Invalid argument\\n"; "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 // GdbEngine
@@ -2651,7 +2662,7 @@ static void handleShowModuleSymbols(const DebuggerResponse &response,
} }
file.close(); file.close();
file.remove(); file.remove();
Internal::showModuleSymbols(modulePath, symbols); DebuggerEngine::showModuleSymbols(modulePath, symbols);
} else { } else {
AsynchronousMessageBox::critical(GdbEngine::tr("Cannot Read Symbols"), AsynchronousMessageBox::critical(GdbEngine::tr("Cannot Read Symbols"),
GdbEngine::tr("Cannot read symbols for module \"%1\".").arg(fileName)); GdbEngine::tr("Cannot read symbols for module \"%1\".").arg(fileName));
@@ -2716,7 +2727,7 @@ void GdbEngine::handleShowModuleSections(const DebuggerResponse &response,
} }
} }
if (!sections.isEmpty()) 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"); DebuggerCommand cmd("fetchSymbols");
cmd.arg("module", moduleName); cmd.arg("module", moduleName);
cmd.callback = [moduleName](const DebuggerResponse &response) { cmd.callback = [this, moduleName](const DebuggerResponse &response) {
const GdbMi &symbols = response.data["symbols"]; const GdbMi &symbols = response.data["symbols"];
QString moduleName = response.data["module"].data(); QString moduleName = response.data["module"].data();
Symbols syms; Symbols syms;
@@ -682,7 +682,7 @@ void LldbEngine::requestModuleSymbols(const QString &moduleName)
symbol.demangled = item["demangled"].data(); symbol.demangled = item["demangled"].data();
syms.append(symbol); syms.append(symbol);
} }
Internal::showModuleSymbols(moduleName, syms); showModuleSymbols(moduleName, syms);
}; };
runCommand(cmd); runCommand(cmd);
} }

View File

@@ -369,7 +369,7 @@ void PdbEngine::refreshSymbols(const GdbMi &symbols)
symbol.name = item["name"].data(); symbol.name = item["name"].data();
syms.append(symbol); syms.append(symbol);
} }
Internal::showModuleSymbols(moduleName, syms); showModuleSymbols(moduleName, syms);
} }
bool PdbEngine::canHandleToolTip(const DebuggerToolTipContext &) const 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. // Go backwards in case someone has identical variables in the same scope.
// Fixme: loop variables or similar are currently seen in the outer scope // Fixme: loop variables or similar are currently seen in the outer scope
for (int s = scope->memberCount() - 1; s >= 0; --s){ 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()) { if (symbol->isDeclaration()) {
// Find out about shadowed symbols by bookkeeping // Find out about shadowed symbols by bookkeeping
// the already seen occurrences in a hash. // the already seen occurrences in a hash.
@@ -197,7 +197,7 @@ QStringList getUninitializedVariables(const Snapshot &snapshot,
const Document::Ptr doc = docIt.value(); const Document::Ptr doc = docIt.value();
// Look at symbol at line and find its function. Either it is the // Look at symbol at line and find its function. Either it is the
// function itself or some expression/variable. // function itself or some expression/variable.
const Symbol *symbolAtLine = doc->lastVisibleSymbolAt(line, 0); const CPlusPlus::Symbol *symbolAtLine = doc->lastVisibleSymbolAt(line, 0);
if (!symbolAtLine) if (!symbolAtLine)
return result; return result;
// First figure out the function to do a safety name check // 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) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/litehtml/CMakeLists.txt)
set(ORIG_FPIC ${CMAKE_POSITION_INDEPENDENT_CODE}) 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) if (WIN32)
set(LITEHTML_UTF8 ON) set(LITEHTML_UTF8 ON)
endif() endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(litehtml) add_subdirectory(litehtml)
set(CMAKE_BUILD_TYPE ${ORIG_CMAKE_BUILD_TYPE})
set(CMAKE_POSITION_INDEPENDENT_CODE "${ORIG_FPIC}") 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() else()
find_package(litehtml REQUIRED) find_package(litehtml REQUIRED)
endif() endif()

View File

@@ -652,11 +652,9 @@ void DocumentContainer::buildIndex()
void DocumentContainer::draw_background(litehtml::uint_ptr hdc, const litehtml::background_paint &bg) void DocumentContainer::draw_background(litehtml::uint_ptr hdc, const litehtml::background_paint &bg)
{ {
// TODO
auto painter = toQPainter(hdc); auto painter = toQPainter(hdc);
if (bg.is_root) { if (bg.is_root) {
// TODO ? // TODO ?
drawSelection(painter, toQRect(bg.border_box));
return; return;
} }
painter->save(); painter->save();
@@ -935,6 +933,14 @@ void DocumentContainer::render(int width, int height)
m_selection.update(); 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, QVector<QRect> DocumentContainer::mousePressEvent(const QPoint &documentPos,
const QPoint &viewportPos, const QPoint &viewportPos,
Qt::MouseButton button) Qt::MouseButton button)

View File

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

View File

@@ -523,17 +523,11 @@ void QLiteHtmlWidget::paintEvent(QPaintEvent *event)
if (!d->documentContainer.document()) if (!d->documentContainer.document())
return; return;
d->documentContainer.setScrollPosition(scrollPosition()); 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()); QPainter p(viewport());
p.setWorldTransform(QTransform().scale(d->zoomFactor, d->zoomFactor)); p.setWorldTransform(QTransform().scale(d->zoomFactor, d->zoomFactor));
p.setRenderHint(QPainter::SmoothPixmapTransform, true); p.setRenderHint(QPainter::SmoothPixmapTransform, true);
p.setRenderHint(QPainter::Antialiasing, true); p.setRenderHint(QPainter::Antialiasing, true);
d->documentContainer.document()->draw(reinterpret_cast<litehtml::uint_ptr>(&p), d->documentContainer.draw(&p, toVirtual(event->rect()));
pos.x(),
pos.y(),
&clip);
} }
static litehtml::element::ptr elementForY(int y, const litehtml::document::ptr &document) 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", const QIcon icon = Utils::Icon({{":/languageclient/images/languageclient.png",
Utils::Theme::IconsBaseColor}}) Utils::Theme::IconsBaseColor}})
.icon(); .icon();
actions[widget] = widget->toolBar()->addAction(icon, client->name(), [document]() { actions[widget] = widget->toolBar()->addAction(
auto menu = new QMenu; icon, client->name(), [document]() {
for (auto client : LanguageClientManager::clientsSupportingDocument(document)) auto menu = new QMenu;
menu->addAction(client->name(), [client = QPointer<Client>(client), document]() { auto *clientsGroup = new QActionGroup(menu);
if (client) 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); 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...", []() { menu->popup(QCursor::pos());
Core::ICore::showOptionsDialog(Constants::LANGUAGECLIENT_SETTINGS_PAGE);
}); });
menu->popup(QCursor::pos());
});
QObject::connect(widget, &QWidget::destroyed, [widget]() { QObject::connect(widget, &QWidget::destroyed, [widget]() {
actions.remove(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) 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") if ((tcd.language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|| fileName.endsWith("gcc"))) || fileName.endsWith("gcc")))
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++") || (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) 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") if ((tcd.language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|| fileName.endsWith("gcc"))) || fileName.endsWith("gcc")))
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++") || (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")

View File

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

View File

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

View File

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

View File

@@ -25,40 +25,241 @@
#include "pythoneditor.h" #include "pythoneditor.h"
#include "pythonconstants.h" #include "pythonconstants.h"
#include "pythonplugin.h"
#include "pythonindenter.h"
#include "pythonhighlighter.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/texteditoractionhandler.h>
#include <texteditor/texteditorconstants.h> #include <texteditor/texteditorconstants.h>
#include <texteditor/textdocument.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/synchronousprocess.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <QRegularExpression>
using namespace TextEditor; using namespace ProjectExplorer;
using namespace Utils;
namespace Python { namespace Python {
namespace Internal { 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() PythonEditorFactory::PythonEditorFactory()
{ {
setId(Constants::C_PYTHONEDITOR_ID); 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); addMimeType(Constants::C_PY_MIMETYPE);
setEditorActionHandlers(TextEditorActionHandler::Format setEditorActionHandlers(TextEditor::TextEditorActionHandler::Format
| TextEditorActionHandler::UnCommentSelection | TextEditor::TextEditorActionHandler::UnCommentSelection
| TextEditorActionHandler::UnCollapseAll | TextEditor::TextEditorActionHandler::UnCollapseAll
| TextEditorActionHandler::FollowSymbolUnderCursor); | 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); }); setIndenterCreator([](QTextDocument *doc) { return new PythonIndenter(doc); });
setSyntaxHighlighterCreator([] { return new PythonHighlighter; }); setSyntaxHighlighterCreator([] { return new PythonHighlighter; });
setCommentDefinition(Utils::CommentDefinition::HashStyle); setCommentDefinition(CommentDefinition::HashStyle);
setParenthesesMatchingEnabled(true); setParenthesesMatchingEnabled(true);
setCodeFoldingSupported(true); setCodeFoldingSupported(true);
connect(Core::EditorManager::instance(), &Core::EditorManager::documentOpened,
this, documentOpened);
} }
} // namespace Internal } // namespace Internal

View File

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

View File

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

View File

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