forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/master' into 4.11
Change-Id: I039c82e198863e8506723c9fb7a37ca51260afd3
This commit is contained in:
Binary file not shown.
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 22 KiB |
@@ -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)}.
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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> §ions);
|
||||
|
||||
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,
|
||||
|
@@ -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 §ions)
|
||||
{
|
||||
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
|
||||
|
@@ -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> §ions);
|
||||
|
||||
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;
|
||||
|
||||
|
@@ -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 §ions)
|
||||
{
|
||||
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)
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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)
|
||||
|
@@ -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,
|
||||
|
@@ -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)
|
||||
|
@@ -218,13 +218,24 @@ 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]() {
|
||||
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)
|
||||
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);
|
||||
});
|
||||
|
@@ -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++")
|
||||
|
@@ -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
|
||||
|
@@ -9,6 +9,7 @@ QtcPlugin {
|
||||
Depends { name: "Core" }
|
||||
Depends { name: "TextEditor" }
|
||||
Depends { name: "ProjectExplorer" }
|
||||
Depends { name: "LanguageClient" }
|
||||
|
||||
Group {
|
||||
name: "General"
|
||||
|
@@ -4,5 +4,6 @@ QTC_LIB_DEPENDS += \
|
||||
utils
|
||||
QTC_PLUGIN_DEPENDS += \
|
||||
coreplugin \
|
||||
texteditor \
|
||||
projectexplorer
|
||||
languageclient \
|
||||
projectexplorer \
|
||||
texteditor
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
};
|
||||
|
@@ -801,11 +801,20 @@ void TimelineBarItem::itemMoved(const QPointF &start, const QPointF &end)
|
||||
if (isActiveHandle(Location::Undefined))
|
||||
dragInit(rect(), start);
|
||||
|
||||
const qreal min = qreal(TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset
|
||||
qreal min = qreal(TimelineConstants::sectionWidth + TimelineConstants::timelineLeftOffset
|
||||
- scrollOffset());
|
||||
const qreal max = qreal(timelineScene()->rulerWidth() - TimelineConstants::sectionWidth
|
||||
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);
|
||||
else
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user