diff options
author | Eike Ziller <eike.ziller@qt.io> | 2018-01-17 08:40:59 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2018-01-17 08:40:59 +0000 |
commit | d6ee830ec183f60c66823374669ee0326c9ec9b9 (patch) | |
tree | 2bfcc777ad86bd361dd88429ba349caaae5e2646 /src/plugins | |
parent | 507e2b99cb49b60e805e266f4f2f7cf6da150ebe (diff) | |
parent | 115afed94b8e85db29b0c057e7c143a3d053d6cc (diff) | |
download | qt-creator-d6ee830ec183f60c66823374669ee0326c9ec9b9.tar.gz |
Merge "Merge remote-tracking branch 'origin/4.6'"
Diffstat (limited to 'src/plugins')
51 files changed, 1352 insertions, 415 deletions
diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp index 1e885ac73a..1bfabb42db 100644 --- a/src/plugins/autotest/qtest/qttestparser.cpp +++ b/src/plugins/autotest/qtest/qttestparser.cpp @@ -271,6 +271,13 @@ static QtTestCodeLocationList tagLocationsFor(const QtTestParseResult *func, return QtTestCodeLocationList(); } +static bool isQObject(const CPlusPlus::Document::Ptr &declaringDoc) +{ + const QString file = declaringDoc->fileName(); + return (Utils::HostOsInfo::isMacHost() && file.endsWith("QtCore.framework/Headers/qobject.h")) + || file.endsWith("QtCore/qobject.h") || file.endsWith("kernel/qobject.h"); +} + static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface, CPlusPlus::Document::Ptr document, const CPlusPlus::Snapshot &snapshot, @@ -303,6 +310,10 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface, fetchAndMergeBaseTestFunctions( visitor.baseClasses(), testFunctions, declaringDoc, snapshot); + // handle tests that are not runnable without more information (plugin unit test of QC) + if (testFunctions.isEmpty() && testCaseName == "QObject" && isQObject(declaringDoc)) + return true; // we did not handle it, but we do not expect any test defined there either + const QSet<QString> &files = filesWithDataFunctionDefinitions(testFunctions); // TODO: change to QHash<> diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp index 5650479312..1abd6982ed 100644 --- a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp +++ b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp @@ -392,6 +392,15 @@ QFuture<CppTools::CursorInfo> BackendCommunicator::requestLocalReferences( return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument); } +QFuture<CppTools::ToolTipInfo> BackendCommunicator::requestToolTip( + const FileContainer &fileContainer, quint32 line, quint32 column) +{ + const RequestToolTipMessage message(fileContainer, line, column); + m_sender->requestToolTip(message); + + return m_receiver.addExpectedToolTipMessage(message.ticketNumber()); +} + QFuture<CppTools::SymbolInfo> BackendCommunicator::requestFollowSymbol( const FileContainer &curFileContainer, quint32 line, diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.h b/src/plugins/clangcodemodel/clangbackendcommunicator.h index bd7494a6c2..b3cb166a39 100644 --- a/src/plugins/clangcodemodel/clangbackendcommunicator.h +++ b/src/plugins/clangcodemodel/clangbackendcommunicator.h @@ -82,6 +82,9 @@ public: quint32 line, quint32 column, QTextDocument *textDocument); + QFuture<CppTools::ToolTipInfo> requestToolTip(const FileContainer &fileContainer, + quint32 line, + quint32 column); QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer, quint32 line, quint32 column); diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp index 8d5ec92d00..f2606d74cc 100644 --- a/src/plugins/clangcodemodel/clangbackendreceiver.cpp +++ b/src/plugins/clangcodemodel/clangbackendreceiver.cpp @@ -128,6 +128,18 @@ QFuture<CppTools::SymbolInfo> BackendReceiver::addExpectedRequestFollowSymbolMes return futureInterface.future(); } +QFuture<CppTools::ToolTipInfo> BackendReceiver::addExpectedToolTipMessage(quint64 ticket) +{ + QTC_CHECK(!m_toolTipsTable.contains(ticket)); + + QFutureInterface<CppTools::ToolTipInfo> futureInterface; + futureInterface.reportStarted(); + + m_toolTipsTable.insert(ticket, futureInterface); + + return futureInterface.future(); +} + bool BackendReceiver::isExpectingCodeCompletedMessage() const { return !m_assistProcessorsTable.isEmpty(); @@ -272,6 +284,72 @@ void BackendReceiver::references(const ReferencesMessage &message) futureInterface.reportFinished(); } +static TextEditor::HelpItem::Category toHelpItemCategory(ToolTipInfo::QdocCategory category) +{ + switch (category) { + case ToolTipInfo::Unknown: + return TextEditor::HelpItem::Unknown; + case ToolTipInfo::ClassOrNamespace: + return TextEditor::HelpItem::ClassOrNamespace; + case ToolTipInfo::Enum: + return TextEditor::HelpItem::Enum; + case ToolTipInfo::Typedef: + return TextEditor::HelpItem::Typedef; + case ToolTipInfo::Macro: + return TextEditor::HelpItem::Macro; + case ToolTipInfo::Brief: + return TextEditor::HelpItem::Brief; + case ToolTipInfo::Function: + return TextEditor::HelpItem::Function; + } + + return TextEditor::HelpItem::Unknown; +} + +static QStringList toStringList(const Utf8StringVector &utf8StringVector) +{ + QStringList list; + list.reserve(utf8StringVector.size()); + + for (const Utf8String &utf8String : utf8StringVector) + list << utf8String.toString(); + + return list; +} + +static CppTools::ToolTipInfo toToolTipInfo(const ToolTipMessage &message) +{ + CppTools::ToolTipInfo info; + + const ToolTipInfo backendInfo = message.toolTipInfo(); + + info.text = backendInfo.text(); + info.briefComment = backendInfo.briefComment(); + + info.qDocIdCandidates = toStringList(backendInfo.qdocIdCandidates()); + info.qDocMark = backendInfo.qdocMark(); + info.qDocCategory = toHelpItemCategory(backendInfo.qdocCategory()); + + info.sizeInBytes = backendInfo.sizeInBytes(); + + return info; +} + +void BackendReceiver::tooltip(const ToolTipMessage &message) +{ + qCDebugIpc() << "ToolTipMessage" << message.toolTipInfo().text(); + + const quint64 ticket = message.ticketNumber(); + QFutureInterface<CppTools::ToolTipInfo> futureInterface = m_toolTipsTable.take(ticket); + QTC_CHECK(futureInterface != QFutureInterface<CppTools::ToolTipInfo>()); + + if (futureInterface.isCanceled()) + return; // A new request was issued making this one outdated. + + futureInterface.reportResult(toToolTipInfo(message)); + futureInterface.reportFinished(); +} + void BackendReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message) { qCDebugIpc() << "FollowSymbolMessage with" diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.h b/src/plugins/clangcodemodel/clangbackendreceiver.h index d7a966eae9..921150a52d 100644 --- a/src/plugins/clangcodemodel/clangbackendreceiver.h +++ b/src/plugins/clangcodemodel/clangbackendreceiver.h @@ -27,6 +27,7 @@ #include <cpptools/cppcursorinfo.h> #include <cpptools/cppsymbolinfo.h> +#include <cpptools/baseeditordocumentprocessor.h> #include <clangsupport/clangcodemodelclientinterface.h> @@ -59,6 +60,7 @@ public: const CppTools::SemanticInfo::LocalUseMap &localUses = CppTools::SemanticInfo::LocalUseMap()); QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket); + QFuture<CppTools::ToolTipInfo> addExpectedToolTipMessage(quint64 ticket); bool isExpectingCodeCompletedMessage() const; void reset(); @@ -70,6 +72,7 @@ private: void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &message) override; void references(const ClangBackEnd::ReferencesMessage &message) override; + void tooltip(const ClangBackEnd::ToolTipMessage &message) override; void followSymbol(const ClangBackEnd::FollowSymbolMessage &message) override; private: @@ -89,7 +92,7 @@ private: CppTools::SemanticInfo::LocalUseMap localUses; }; QHash<quint64, ReferencesEntry> m_referencesTable; - + QHash<quint64, QFutureInterface<CppTools::ToolTipInfo>> m_toolTipsTable; QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable; }; diff --git a/src/plugins/clangcodemodel/clangbackendsender.cpp b/src/plugins/clangcodemodel/clangbackendsender.cpp index 089377083f..f6f8aea1cf 100644 --- a/src/plugins/clangcodemodel/clangbackendsender.cpp +++ b/src/plugins/clangcodemodel/clangbackendsender.cpp @@ -120,6 +120,13 @@ void BackendSender::requestReferences(const RequestReferencesMessage &message) m_connection->serverProxy().requestReferences(message); } +void BackendSender::requestToolTip(const RequestToolTipMessage &message) +{ + QTC_CHECK(m_connection->isConnected()); + qCDebug(ipcLog) << ">>>" << message; + m_connection->serverProxy().requestToolTip(message); +} + void BackendSender::requestFollowSymbol(const RequestFollowSymbolMessage &message) { QTC_CHECK(m_connection->isConnected()); diff --git a/src/plugins/clangcodemodel/clangbackendsender.h b/src/plugins/clangcodemodel/clangbackendsender.h index ca9238ae65..f01326a4dc 100644 --- a/src/plugins/clangcodemodel/clangbackendsender.h +++ b/src/plugins/clangcodemodel/clangbackendsender.h @@ -48,6 +48,7 @@ public: void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override; void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override; void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override; + void requestToolTip(const ClangBackEnd::RequestToolTipMessage &message) override; void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override; void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) override; diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro index 9136db5db5..0e444a350e 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.pro +++ b/src/plugins/clangcodemodel/clangcodemodel.pro @@ -30,6 +30,7 @@ SOURCES += \ clangfixitoperationsextractor.cpp \ clangfollowsymbol.cpp \ clangfunctionhintmodel.cpp \ + clanghoverhandler.cpp \ clangtokeninfosreporter.cpp \ clangmodelmanagersupport.cpp \ clangpreprocessorassistproposalitem.cpp \ @@ -66,6 +67,7 @@ HEADERS += \ clangfixitoperationsextractor.h \ clangfollowsymbol.h \ clangfunctionhintmodel.h \ + clanghoverhandler.h \ clangisdiagnosticrelatedtolocation.h \ clangmodelmanagersupport.h \ clangpreprocessorassistproposalitem.h \ diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs index cc81025925..90105b86d3 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.qbs +++ b/src/plugins/clangcodemodel/clangcodemodel.qbs @@ -80,6 +80,8 @@ QtcPlugin { "clangfollowsymbol.h", "clangfunctionhintmodel.cpp", "clangfunctionhintmodel.h", + "clanghoverhandler.cpp", + "clanghoverhandler.h", "clangtokeninfosreporter.cpp", "clangtokeninfosreporter.h", "clangisdiagnosticrelatedtolocation.h", diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 6eb98b2c92..a282350f24 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -375,6 +375,15 @@ ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column) static_cast<quint32>(column)); } +QFuture<CppTools::ToolTipInfo> ClangEditorDocumentProcessor::toolTipInfo(const QByteArray &codecName, + int line, + int column) +{ + return m_communicator.requestToolTip(simpleFileContainer(codecName), + static_cast<quint32>(line), + static_cast<quint32>(column)); +} + ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const { return fileContainerWithArguments(m_projectPart.data()); @@ -480,13 +489,19 @@ ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget( }; } -ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer() const +ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer( + const QByteArray &codecName) const { Utf8String projectPartId; if (m_projectPart) projectPartId = m_projectPart->id(); - return ClangBackEnd::FileContainer(filePath(), projectPartId, Utf8String(), false, revision()); + return ClangBackEnd::FileContainer(filePath(), + projectPartId, + Utf8String(), + false, + revision(), + Utf8String::fromByteArray(codecName)); } static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart) diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index 2bb7ca0463..67745b582c 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -88,6 +88,9 @@ public: QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams ¶ms) override; QFuture<CppTools::CursorInfo> requestLocalReferences(const QTextCursor &cursor) override; QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line, int column) override; + QFuture<CppTools::ToolTipInfo> toolTipInfo(const QByteArray &codecName, + int line, + int column) override; ClangBackEnd::FileContainer fileContainerWithArguments() const; @@ -106,7 +109,7 @@ private: void requestDocumentAnnotations(const QString &projectpartId); HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget( const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic); - ClangBackEnd::FileContainer simpleFileContainer() const; + ClangBackEnd::FileContainer simpleFileContainer(const QByteArray &codecName = QByteArray()) const; ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const; ClangBackEnd::FileContainer fileContainerWithArgumentsAndDocumentContent( CppTools::ProjectPart *projectPart) const; diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp new file mode 100644 index 0000000000..6610b555c2 --- /dev/null +++ b/src/plugins/clangcodemodel/clanghoverhandler.cpp @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "clanghoverhandler.h" + +#include <coreplugin/helpmanager.h> +#include <cpptools/baseeditordocumentprocessor.h> +#include <cpptools/cppmodelmanager.h> +#include <cpptools/editordocumenthandle.h> +#include <texteditor/texteditor.h> + +#include <utils/qtcassert.h> +#include <utils/textutils.h> +#include <utils/tooltip/tooltip.h> + +#include <QFutureWatcher> +#include <QLoggingCategory> +#include <QTextCodec> +#include <QVBoxLayout> + +Q_LOGGING_CATEGORY(hoverLog, "qtc.clangcodemodel.hover"); + +using namespace TextEditor; + +namespace ClangCodeModel { +namespace Internal { + +static CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(TextEditorWidget *editorWidget) +{ + const QString filePath = editorWidget->textDocument()->filePath().toString(); + auto cppModelManager = CppTools::CppModelManager::instance(); + CppTools::CppEditorDocumentHandle *editorHandle = cppModelManager->cppEditorDocument(filePath); + + if (editorHandle) + return editorHandle->processor(); + + return 0; +} + +static bool editorDocumentProcessorHasDiagnosticAt(TextEditorWidget *editorWidget, int pos) +{ + if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) { + int line, column; + if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column)) + return processor->hasDiagnosticsAt(line, column); + } + + return false; +} + +static void processWithEditorDocumentProcessor(TextEditorWidget *editorWidget, + const QPoint &point, + int position, + const QString &helpId) +{ + if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) { + int line, column; + if (Utils::Text::convertPosition(editorWidget->document(), position, &line, &column)) { + auto layout = new QVBoxLayout; + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(2); + processor->addDiagnosticToolTipToLayout(line, column, layout); + Utils::ToolTip::show(point, layout, editorWidget, helpId); + } + } +} + +static QFuture<CppTools::ToolTipInfo> editorDocumentHandlesToolTipInfo( + TextEditorWidget *editorWidget, int pos) +{ + const QByteArray textCodecName = editorWidget->textDocument()->codec()->name(); + if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) { + int line, column; + if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column)) + return processor->toolTipInfo(textCodecName, line, column + 1); + } + + return QFuture<CppTools::ToolTipInfo>(); +} + +ClangHoverHandler::ClangHoverHandler() +{ + setIsAsyncHandler(true); +} + +ClangHoverHandler::~ClangHoverHandler() +{ + cancelAsyncCheck(); +} + +void ClangHoverHandler::identifyMatchAsync(TextEditorWidget *editorWidget, + int pos, + BaseHoverHandler::ReportPriority report) +{ + // Reset + m_futureWatcher.reset(); + m_cursorPosition = -1; + + // Check for diagnostics (sync) + if (editorDocumentProcessorHasDiagnosticAt(editorWidget, pos)) { + qCDebug(hoverLog) << "Checking for diagnostic at" << pos; + setPriority(Priority_Diagnostic); + m_cursorPosition = pos; + report(priority()); + return; + } + + // Check for tooltips (async) + QFuture<CppTools::ToolTipInfo> future = editorDocumentHandlesToolTipInfo(editorWidget, pos); + if (QTC_GUARD(future.isRunning())) { + qCDebug(hoverLog) << "Requesting tooltip info at" << pos; + m_reportPriority = report; + m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>()); + QObject::connect(m_futureWatcher.data(), &QFutureWatcherBase::finished, [this]() { + processToolTipInfo(m_futureWatcher->result()); + }); + m_futureWatcher->setFuture(future); + return; + } + + report(Priority_None); // Ops, something went wrong. +} + +void ClangHoverHandler::cancelAsyncCheck() +{ + if (m_futureWatcher) + m_futureWatcher->cancel(); +} + +#define RETURN_TEXT_FOR_CASE(enumValue) case TextEditor::HelpItem::enumValue: return #enumValue +static const char *helpItemCategoryAsString(TextEditor::HelpItem::Category category) +{ + switch (category) { + RETURN_TEXT_FOR_CASE(Unknown); + RETURN_TEXT_FOR_CASE(ClassOrNamespace); + RETURN_TEXT_FOR_CASE(Enum); + RETURN_TEXT_FOR_CASE(Typedef); + RETURN_TEXT_FOR_CASE(Macro); + RETURN_TEXT_FOR_CASE(Brief); + RETURN_TEXT_FOR_CASE(Function); + RETURN_TEXT_FOR_CASE(QmlComponent); + RETURN_TEXT_FOR_CASE(QmlProperty); + RETURN_TEXT_FOR_CASE(QMakeVariableOfFunction); + } + + return "UnhandledHelpItemCategory"; +} +#undef RETURN_TEXT_FOR_CASE + +void ClangHoverHandler::processToolTipInfo(const CppTools::ToolTipInfo &info) +{ + qCDebug(hoverLog) << "Processing tooltip info" << info.text; + + QString text = info.text; + if (!info.briefComment.isEmpty()) + text.append("\n\n" + info.briefComment); + + for (const QString &qdocIdCandidate : info.qDocIdCandidates) { + qCDebug(hoverLog) << "Querying help manager with" + << qdocIdCandidate + << info.qDocMark + << helpItemCategoryAsString(info.qDocCategory); + const QMap<QString, QUrl> helpLinks = Core::HelpManager::linksForIdentifier(qdocIdCandidate); + if (!helpLinks.isEmpty()) { + qCDebug(hoverLog) << " Match!"; + setLastHelpItemIdentified( + HelpItem(qdocIdCandidate, info.qDocMark, info.qDocCategory, helpLinks)); + break; + } + } + + if (!info.sizeInBytes.isEmpty()) + text.append(tr("\n\n%1 bytes").arg(info.sizeInBytes)); + + setToolTip(text); + m_reportPriority(priority()); +} + +void ClangHoverHandler::decorateToolTip() +{ + if (priority() == Priority_Diagnostic) + return; + + if (Qt::mightBeRichText(toolTip())) + setToolTip(toolTip().toHtmlEscaped()); + + const HelpItem &help = lastHelpItemIdentified(); + if (help.isValid()) { + const QString text = CppTools::CppHoverHandler::tooltipTextForHelpItem(help); + if (!text.isEmpty()) + setToolTip(text); + } +} + +void ClangHoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget, + const QPoint &point) +{ + if (priority() == Priority_Diagnostic) { + const HelpItem helpItem = lastHelpItemIdentified(); + const QString helpId = helpItem.isValid() ? helpItem.helpId() : QString(); + processWithEditorDocumentProcessor(editorWidget, point, m_cursorPosition, helpId); + return; + } + + // Priority_Tooltip / Priority_Help + BaseHoverHandler::operateTooltip(editorWidget, point); +} + +} // namespace Internal +} // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clanghoverhandler.h b/src/plugins/clangcodemodel/clanghoverhandler.h new file mode 100644 index 0000000000..85b7999f94 --- /dev/null +++ b/src/plugins/clangcodemodel/clanghoverhandler.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <cpptools/baseeditordocumentprocessor.h> +#include <cpptools/cpphoverhandler.h> +#include <texteditor/basehoverhandler.h> + +namespace ClangCodeModel { +namespace Internal { + +class ClangHoverHandler : public TextEditor::BaseHoverHandler +{ + Q_DECLARE_TR_FUNCTIONS(ClangHoverHandler) + +public: + ClangHoverHandler(); + ~ClangHoverHandler() override; + + void identifyMatchAsync(TextEditor::TextEditorWidget *editorWidget, + int pos, + ReportPriority report) override; + void decorateToolTip() override; + void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override; + +private: + void cancelAsyncCheck() override; + void processToolTipInfo(const CppTools::ToolTipInfo &info); + +private: + int m_cursorPosition = -1; + QScopedPointer<QFutureWatcher<CppTools::ToolTipInfo>> m_futureWatcher; + ReportPriority m_reportPriority; +}; + +} // namespace Internal +} // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index f73c5fe4e4..9495e6d5eb 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -29,6 +29,7 @@ #include "clangeditordocumentprocessor.h" #include "clangutils.h" #include "clangfollowsymbol.h" +#include "clanghoverhandler.h" #include "clangrefactoringengine.h" #include <coreplugin/editormanager/editormanager.h> @@ -111,6 +112,11 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssis return &m_completionAssistProvider; } +TextEditor::BaseHoverHandler *ModelManagerSupportClang::createHoverHandler() +{ + return new Internal::ClangHoverHandler; +} + CppTools::FollowSymbolInterface &ModelManagerSupportClang::followSymbolInterface() { return *m_followSymbol; @@ -121,7 +127,7 @@ CppTools::RefactoringEngineInterface &ModelManagerSupportClang::refactoringEngin return *m_refactoringEngine; } -CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor( +CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) { return new ClangEditorDocumentProcessor(m_communicator, baseTextDocument); diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index e87a7f162e..92f253c5a8 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -61,7 +61,8 @@ public: ~ModelManagerSupportClang(); CppTools::CppCompletionAssistProvider *completionAssistProvider() override; - CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor( + TextEditor::BaseHoverHandler *createHoverHandler() override; + CppTools::BaseEditorDocumentProcessor *createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) override; CppTools::FollowSymbolInterface &followSymbolInterface() override; CppTools::RefactoringEngineInterface &refactoringEngineInterface() override; diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index 65fba9709f..577a9f9487 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -26,12 +26,13 @@ #include "coreplugin.h" #include "designmode.h" #include "editmode.h" -#include "idocument.h" #include "helpmanager.h" -#include "mainwindow.h" -#include "modemanager.h" +#include "idocument.h" #include "infobar.h" #include "iwizardfactory.h" +#include "mainwindow.h" +#include "menubarfilter.h" +#include "modemanager.h" #include "reaper_p.h" #include "themechooser.h" @@ -162,6 +163,8 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage) InfoBar::initialize(ICore::settings(), creatorTheme()); } + addAutoReleasedObject(new MenuBarFilter); + IWizardFactory::initialize(); // Make sure we respect the process's umask when creating new files diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro index dd6f03bdaa..d5f1f7f51e 100644 --- a/src/plugins/coreplugin/coreplugin.pro +++ b/src/plugins/coreplugin/coreplugin.pro @@ -111,7 +111,8 @@ SOURCES += corejsextensions.cpp \ externaltoolmanager.cpp \ systemsettings.cpp \ coreicons.cpp \ - diffservice.cpp + diffservice.cpp \ + menubarfilter.cpp HEADERS += corejsextensions.h \ mainwindow.h \ @@ -222,7 +223,8 @@ HEADERS += corejsextensions.h \ systemsettings.h \ coreicons.h \ editormanager/documentmodel_p.h \ - diffservice.h + diffservice.h \ + menubarfilter.h FORMS += dialogs/newdialog.ui \ dialogs/saveitemsdialog.ui \ diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index eabf668df7..ce47658daa 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -32,79 +32,154 @@ Project { Group { name: "General" files: [ - "basefilewizard.cpp", "basefilewizard.h", - "basefilewizardfactory.cpp", "basefilewizardfactory.h", + "basefilewizard.cpp", + "basefilewizard.h", + "basefilewizardfactory.cpp", + "basefilewizardfactory.h", "core.qrc", "core_global.h", "coreconstants.h", - "coreicons.cpp", "coreicons.h", - "corejsextensions.cpp", "corejsextensions.h", - "coreplugin.cpp", "coreplugin.h", - "designmode.cpp", "designmode.h", - "diffservice.cpp", "diffservice.h", - "documentmanager.cpp", "documentmanager.h", - "editmode.cpp", "editmode.h", - "editortoolbar.cpp", "editortoolbar.h", - "externaltool.cpp", "externaltool.h", - "externaltoolmanager.cpp", "externaltoolmanager.h", - "fancyactionbar.cpp", "fancyactionbar.h", "fancyactionbar.qrc", - "fancytabwidget.cpp", "fancytabwidget.h", - "featureprovider.cpp", "featureprovider.h", - "fileiconprovider.cpp", "fileiconprovider.h", - "fileutils.cpp", "fileutils.h", - "findplaceholder.cpp", "findplaceholder.h", - "generalsettings.cpp", "generalsettings.h", "generalsettings.ui", - "generatedfile.cpp", "generatedfile.h", - "helpmanager.cpp", "helpmanager.h", - "icontext.cpp", "icontext.h", - "icore.cpp", "icore.h", - "id.cpp", "id.h", - "idocument.cpp", "idocument.h", - "idocumentfactory.cpp", "idocumentfactory.h", + "coreicons.cpp", + "coreicons.h", + "corejsextensions.cpp", + "corejsextensions.h", + "coreplugin.cpp", + "coreplugin.h", + "designmode.cpp", + "designmode.h", + "diffservice.cpp", + "diffservice.h", + "documentmanager.cpp", + "documentmanager.h", + "editmode.cpp", + "editmode.h", + "editortoolbar.cpp", + "editortoolbar.h", + "externaltool.cpp", + "externaltool.h", + "externaltoolmanager.cpp", + "externaltoolmanager.h", + "fancyactionbar.cpp", + "fancyactionbar.h", + "fancyactionbar.qrc", + "fancytabwidget.cpp", + "fancytabwidget.h", + "featureprovider.cpp", + "featureprovider.h", + "fileiconprovider.cpp", + "fileiconprovider.h", + "fileutils.cpp", + "fileutils.h", + "findplaceholder.cpp", + "findplaceholder.h", + "generalsettings.cpp", + "generalsettings.h", + "generalsettings.ui", + "generatedfile.cpp", + "generatedfile.h", + "helpmanager.cpp", + "helpmanager.h", + "icontext.cpp", + "icontext.h", + "icore.cpp", + "icore.h", + "id.cpp", + "id.h", + "idocument.cpp", + "idocument.h", + "idocumentfactory.cpp", + "idocumentfactory.h", "ifilewizardextension.h", - "imode.cpp", "imode.h", - "inavigationwidgetfactory.cpp", "inavigationwidgetfactory.h", - "infobar.cpp", "infobar.h", - "ioutputpane.cpp", "ioutputpane.h", - "iversioncontrol.cpp", "iversioncontrol.h", - "iwelcomepage.cpp", "iwelcomepage.h", - "iwizardfactory.cpp", "iwizardfactory.h", - "jsexpander.cpp", "jsexpander.h", - "mainwindow.cpp", "mainwindow.h", - "manhattanstyle.cpp", "manhattanstyle.h", - "messagebox.cpp", "messagebox.h", - "messagemanager.cpp", "messagemanager.h", - "messageoutputwindow.cpp", "messageoutputwindow.h", - "mimetypemagicdialog.cpp", "mimetypemagicdialog.h", "mimetypemagicdialog.ui", - "mimetypesettings.cpp", "mimetypesettings.h", + "imode.cpp", + "imode.h", + "inavigationwidgetfactory.cpp", + "inavigationwidgetfactory.h", + "infobar.cpp", + "infobar.h", + "ioutputpane.cpp", + "ioutputpane.h", + "iversioncontrol.cpp", + "iversioncontrol.h", + "iwelcomepage.cpp", + "iwelcomepage.h", + "iwizardfactory.cpp", + "iwizardfactory.h", + "jsexpander.cpp", + "jsexpander.h", + "mainwindow.cpp", + "mainwindow.h", + "manhattanstyle.cpp", + "manhattanstyle.h", + "menubarfilter.cpp", + "menubarfilter.h", + "messagebox.cpp", + "messagebox.h", + "messagemanager.cpp", + "messagemanager.h", + "messageoutputwindow.cpp", + "messageoutputwindow.h", + "mimetypemagicdialog.cpp", + "mimetypemagicdialog.h", + "mimetypemagicdialog.ui", + "mimetypesettings.cpp", + "mimetypesettings.h", "mimetypesettingspage.ui", - "minisplitter.cpp", "minisplitter.h", - "modemanager.cpp", "modemanager.h", - "navigationsubwidget.cpp", "navigationsubwidget.h", - "navigationwidget.cpp", "navigationwidget.h", - "opendocumentstreeview.cpp", "opendocumentstreeview.h", - "outputpane.cpp", "outputpane.h", - "outputpanemanager.cpp", "outputpanemanager.h", - "outputwindow.cpp", "outputwindow.h", - "patchtool.cpp", "patchtool.h", - "plugindialog.cpp", "plugindialog.h", - "reaper.cpp", "reaper.h", "reaper_p.h", - "rightpane.cpp", "rightpane.h", - "settingsdatabase.cpp", "settingsdatabase.h", - "shellcommand.cpp", "shellcommand.h", - "sidebar.cpp", "sidebar.h", - "sidebarwidget.cpp", "sidebarwidget.h", - "statusbarmanager.cpp", "statusbarmanager.h", - "statusbarwidget.cpp", "statusbarwidget.h", - "styleanimator.cpp", "styleanimator.h", - "systemsettings.cpp", "systemsettings.h", "systemsettings.ui", - "textdocument.cpp", "textdocument.h", - "themechooser.cpp", "themechooser.h", - "toolsettings.cpp", "toolsettings.h", - "variablechooser.cpp", "variablechooser.h", - "vcsmanager.cpp", "vcsmanager.h", - "versiondialog.cpp", "versiondialog.h", - "windowsupport.cpp", "windowsupport.h" + "minisplitter.cpp", + "minisplitter.h", + "modemanager.cpp", + "modemanager.h", + "navigationsubwidget.cpp", + "navigationsubwidget.h", + "navigationwidget.cpp", + "navigationwidget.h", + "opendocumentstreeview.cpp", + "opendocumentstreeview.h", + "outputpane.cpp", + "outputpane.h", + "outputpanemanager.cpp", + "outputpanemanager.h", + "outputwindow.cpp", + "outputwindow.h", + "patchtool.cpp", + "patchtool.h", + "plugindialog.cpp", + "plugindialog.h", + "reaper.cpp", + "reaper.h", + "reaper_p.h", + "rightpane.cpp", + "rightpane.h", + "settingsdatabase.cpp", + "settingsdatabase.h", + "shellcommand.cpp", + "shellcommand.h", + "sidebar.cpp", + "sidebar.h", + "sidebarwidget.cpp", + "sidebarwidget.h", + "statusbarmanager.cpp", + "statusbarmanager.h", + "statusbarwidget.cpp", + "statusbarwidget.h", + "styleanimator.cpp", + "styleanimator.h", + "systemsettings.cpp", + "systemsettings.h", + "systemsettings.ui", + "textdocument.cpp", + "textdocument.h", + "themechooser.cpp", + "themechooser.h", + "toolsettings.cpp", + "toolsettings.h", + "variablechooser.cpp", + "variablechooser.h", + "vcsmanager.cpp", + "vcsmanager.h", + "versiondialog.cpp", + "versiondialog.h", + "windowsupport.cpp", + "windowsupport.h", ] } @@ -268,6 +343,8 @@ Project { "filesystemfilter.ui", "ilocatorfilter.cpp", "ilocatorfilter.h", + "javascriptfilter.cpp", + "javascriptfilter.h", "locatorconstants.h", "locatorfiltersfilter.cpp", "locatorfiltersfilter.h", diff --git a/src/plugins/coreplugin/locator/javascriptfilter.cpp b/src/plugins/coreplugin/locator/javascriptfilter.cpp new file mode 100644 index 0000000000..02803ecf72 --- /dev/null +++ b/src/plugins/coreplugin/locator/javascriptfilter.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "javascriptfilter.h" + +#include <QClipboard> +#include <QGuiApplication> +#include <QJSEngine> + +namespace Core { +namespace Internal { + +JavaScriptFilter::JavaScriptFilter() +{ + setId("JavaScriptFilter"); + setDisplayName(tr("Evaluate JavaScript")); + setIncludedByDefault(false); + setShortcutString("="); +} + +JavaScriptFilter::~JavaScriptFilter() +{ +} + +void JavaScriptFilter::prepareSearch(const QString &entry) +{ + Q_UNUSED(entry); + + setupEngine(); +} + +QList<LocatorFilterEntry> JavaScriptFilter::matchesFor( + QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry) +{ + Q_UNUSED(future); + + const QString result = m_engine->evaluate(entry).toString(); + const QString expression = entry + " = " + result; + + QList<LocatorFilterEntry> entries; + entries.append({this, expression, QVariant()}); + entries.append({this, tr("Copy to clipboard: %1").arg(result), result}); + entries.append({this, tr("Copy to clipboard: %1").arg(expression), expression}); + + return entries; +} + +void JavaScriptFilter::accept(Core::LocatorFilterEntry selection, QString *newText, + int *selectionStart, int *selectionLength) const +{ + Q_UNUSED(newText); + Q_UNUSED(selectionStart); + Q_UNUSED(selectionLength); + + if (selection.internalData.isNull()) + return; + + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(selection.internalData.toString()); +} + +void JavaScriptFilter::refresh(QFutureInterface<void> &future) +{ + Q_UNUSED(future); + // Nothing to refresh +} + +void JavaScriptFilter::setupEngine() +{ + if (m_engine) + return; + + m_engine = new QJSEngine(this); + m_engine->evaluate( + "function abs(x) { return Math.abs(x); }\n" + "function acos(x) { return Math.acos(x); }\n" + "function asin(x) { return Math.asin(x); }\n" + "function atan(x) { return Math.atan(x); }\n" + "function atan2(x, y) { return Math.atan2(x, y); }\n" + "function bin(x) { return '0b' + x.toString(2); }\n" + "function ceil(x) { return Math.ceil(x); }\n" + "function cos(x) { return Math.cos(x); }\n" + "function exp(x) { return Math.exp(x); }\n" + "function e() { return Math.E; }\n" + "function floor(x) { return Math.floor(x); }\n" + "function hex(x) { return '0x' + x.toString(16); }\n" + "function log(x) { return Math.log(x); }\n" + "function max(x, y) { return Math.max(x, y); }\n" + "function min(x, y) { return Math.min(x, y); }\n" + "function oct(x) { return '0' + x.toString(8); }\n" + "function pi() { return Math.PI; }\n" + "function pow(x, y) { return Math.pow(x, y); }\n" + "function random() { return Math.random(); }\n" + "function round(x) { return Math.round(x); }\n" + "function sin(x) { return Math.sin(x); }\n" + "function sqrt(x) { return Math.sqrt(x); }\n" + "function tan(x) { return Math.tan(x); }\n"); +} + +} // namespace Internal +} // namespace Core diff --git a/src/plugins/coreplugin/locator/javascriptfilter.h b/src/plugins/coreplugin/locator/javascriptfilter.h new file mode 100644 index 0000000000..50f5e85c3b --- /dev/null +++ b/src/plugins/coreplugin/locator/javascriptfilter.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Andre Hartmann <aha_1980@gmx.de> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <coreplugin/locator/ilocatorfilter.h> + +QT_BEGIN_NAMESPACE +class QJSEngine; +QT_END_NAMESPACE + +namespace Core { +namespace Internal { + +class JavaScriptFilter : public Core::ILocatorFilter +{ + Q_OBJECT +public: + JavaScriptFilter(); + ~JavaScriptFilter(); + + virtual void prepareSearch(const QString &entry) override; + QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future, + const QString &entry) override; + void accept(Core::LocatorFilterEntry selection, QString *newText, + int *selectionStart, int *selectionLength) const override; + void refresh(QFutureInterface<void> &future) override; + +private: + void setupEngine(); + + QJSEngine *m_engine = nullptr; +}; + +} // namespace Internal +} // namespace Core diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp index 6daab8026e..e57f20241a 100644 --- a/src/plugins/coreplugin/locator/locator.cpp +++ b/src/plugins/coreplugin/locator/locator.cpp @@ -27,6 +27,7 @@ #include "externaltoolsfilter.h" #include "filesystemfilter.h" +#include "javascriptfilter.h" #include "locatorconstants.h" #include "locatorfiltersfilter.h" #include "locatormanager.h" @@ -75,11 +76,13 @@ Locator::Locator() Locator::~Locator() { + m_corePlugin->removeObject(m_javaScriptFilter); m_corePlugin->removeObject(m_openDocumentsFilter); m_corePlugin->removeObject(m_fileSystemFilter); m_corePlugin->removeObject(m_executeFilter); m_corePlugin->removeObject(m_settingsPage); m_corePlugin->removeObject(m_externalToolsFilter); + delete m_javaScriptFilter; delete m_openDocumentsFilter; delete m_fileSystemFilter; delete m_executeFilter; @@ -119,6 +122,9 @@ void Locator::initialize(CorePlugin *corePlugin, const QStringList &, QString *) new LocatorManager(this); + m_javaScriptFilter = new JavaScriptFilter; + m_corePlugin->addObject(m_javaScriptFilter); + m_openDocumentsFilter = new OpenDocumentsFilter; m_corePlugin->addObject(m_openDocumentsFilter); diff --git a/src/plugins/coreplugin/locator/locator.h b/src/plugins/coreplugin/locator/locator.h index 325bcc1130..5d5d379a88 100644 --- a/src/plugins/coreplugin/locator/locator.h +++ b/src/plugins/coreplugin/locator/locator.h @@ -42,6 +42,7 @@ namespace Internal { class CorePlugin; class OpenDocumentsFilter; class FileSystemFilter; +class JavaScriptFilter; class LocatorSettingsPage; class ExternalToolsFilter; @@ -85,6 +86,7 @@ private: QList<ILocatorFilter *> m_customFilters; QMap<Id, QAction *> m_filterActionMap; QTimer m_refreshTimer; + JavaScriptFilter *m_javaScriptFilter = nullptr; OpenDocumentsFilter *m_openDocumentsFilter = nullptr; FileSystemFilter *m_fileSystemFilter = nullptr; ExecuteFilter *m_executeFilter = nullptr; diff --git a/src/plugins/coreplugin/locator/locator.pri b/src/plugins/coreplugin/locator/locator.pri index e80765bfc5..183d7fde51 100644 --- a/src/plugins/coreplugin/locator/locator.pri +++ b/src/plugins/coreplugin/locator/locator.pri @@ -1,3 +1,5 @@ +QT *= qml + HEADERS += \ $$PWD/locator.h \ $$PWD/commandlocator.h \ @@ -13,7 +15,8 @@ HEADERS += \ $$PWD/executefilter.h \ $$PWD/locatorsearchutils.h \ $$PWD/locatorsettingspage.h \ - $$PWD/externaltoolsfilter.h + $$PWD/externaltoolsfilter.h \ + $$PWD/javascriptfilter.h SOURCES += \ $$PWD/locator.cpp \ @@ -29,7 +32,8 @@ SOURCES += \ $$PWD/executefilter.cpp \ $$PWD/locatorsearchutils.cpp \ $$PWD/locatorsettingspage.cpp \ - $$PWD/externaltoolsfilter.cpp + $$PWD/externaltoolsfilter.cpp \ + $$PWD/javascriptfilter.cpp FORMS += \ $$PWD/filesystemfilter.ui \ diff --git a/src/plugins/coreplugin/menubarfilter.cpp b/src/plugins/coreplugin/menubarfilter.cpp new file mode 100644 index 0000000000..5c3c4414db --- /dev/null +++ b/src/plugins/coreplugin/menubarfilter.cpp @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "menubarfilter.h" + +#include "actionmanager/actioncontainer.h" +#include "actionmanager/actionmanager.h" +#include "coreconstants.h" + +#include <utils/algorithm.h> +#include <utils/asconst.h> +#include <utils/qtcassert.h> +#include <utils/stringutils.h> + +#include <QMenuBar> +#include <QPointer> +#include <QRegularExpression> + +using namespace Core::Internal; +using namespace Core; + +MenuBarFilter::MenuBarFilter() +{ + setId("Actions from the menu"); + setDisplayName(tr("Actions from the Menu")); + setShortcutString("t"); +} + +static const QList<QAction *> menuBarActions() +{ + QMenuBar *menuBar = Core::ActionManager::actionContainer(Constants::MENU_BAR)->menuBar(); + QTC_ASSERT(menuBar, return {}); + return menuBar->actions(); +} + +QList<LocatorFilterEntry> MenuBarFilter::matchesFor(QFutureInterface<LocatorFilterEntry> &future, + const QString &entry) +{ + Q_UNUSED(future); + static const QString separators = ". >/"; + static const QRegularExpression seperatorRegExp(QString("[%1]").arg(separators)); + QList<LocatorFilterEntry> entries; + QString normalized = entry; + normalized.replace(seperatorRegExp, separators.at(0)); + const QStringList entryPath = normalized.split(separators.at(0), QString::SkipEmptyParts); + QVector<const QMenu *> processedMenus; + for (QAction* action : menuBarActions()) + entries << matchesForAction(action, entryPath, QStringList(), processedMenus); + + return entries; +} + +void MenuBarFilter::accept(LocatorFilterEntry selection, QString *newText, + int *selectionStart, int *selectionLength) const +{ + Q_UNUSED(newText); + Q_UNUSED(selectionStart); + Q_UNUSED(selectionLength); + if (auto action = selection.internalData.value<QPointer<QAction>>()) + action->trigger(); +} + +void MenuBarFilter::refresh(QFutureInterface<void> &future) +{ + Q_UNUSED(future); +} + +QList<LocatorFilterEntry> MenuBarFilter::matchesForAction(QAction *action, + const QStringList &entryPath, + const QStringList &path, + QVector<const QMenu *> &processedMenus) +{ + QList<LocatorFilterEntry> entries; + if (!action->isEnabled()) + return entries; + const QString text = Utils::stripAccelerator(action->text()); + if (QMenu *menu = action->menu()) { + if (processedMenus.contains(menu)) + return entries; + processedMenus.append(menu); + if (menu->isEnabled()) { + const QList<QAction *> &actions = menu->actions(); + QStringList menuPath(path); + menuPath << text; + for (QAction *menuAction : actions) + entries << matchesForAction(menuAction, entryPath, menuPath, processedMenus); + } + } else if (!text.isEmpty()) { + int entryIndex = 0; + int entryLength = 0; + int pathIndex = 0; + LocatorFilterEntry::HighlightInfo::DataType highlightType = + LocatorFilterEntry::HighlightInfo::DisplayName; + const QString pathText = path.join(" > "); + QStringList actionPath(path); + if (!entryPath.isEmpty()) { + actionPath << text; + for (const QString &entry : entryPath) { + const QRegularExpression re(".*" + entry + ".*", + QRegularExpression::CaseInsensitiveOption); + pathIndex = actionPath.indexOf(re, pathIndex); + if (pathIndex < 0) + return entries; + } + const QString &lastEntry(entryPath.last()); + entryLength = lastEntry.length(); + entryIndex = text.indexOf(lastEntry, 0, Qt::CaseInsensitive); + if (entryIndex >= 0) { + highlightType = LocatorFilterEntry::HighlightInfo::DisplayName; + } else { + entryIndex = pathText.indexOf(lastEntry, 0, Qt::CaseInsensitive); + QTC_ASSERT(entryIndex >= 0, return entries); + highlightType = LocatorFilterEntry::HighlightInfo::ExtraInfo; + } + } + LocatorFilterEntry filterEntry(this, text, QVariant(), action->icon()); + filterEntry.internalData.setValue(QPointer<QAction>(action)); + filterEntry.extraInfo = pathText; + filterEntry.highlightInfo = {entryIndex, entryLength, highlightType}; + entries << filterEntry; + } + return entries; +} + +static void requestMenuUpdate(const QAction* action) +{ + if (QMenu *menu = action->menu()) { + emit menu->aboutToShow(); + const QList<QAction *> &actions = menu->actions(); + for (const QAction *menuActions : actions) + requestMenuUpdate(menuActions); + } +} + +void Core::Internal::MenuBarFilter::prepareSearch(const QString &entry) +{ + Q_UNUSED(entry); + for (const QAction *action : menuBarActions()) + requestMenuUpdate(action); +} diff --git a/src/plugins/coreplugin/menubarfilter.h b/src/plugins/coreplugin/menubarfilter.h new file mode 100644 index 0000000000..9251df7da2 --- /dev/null +++ b/src/plugins/coreplugin/menubarfilter.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <coreplugin/locator/ilocatorfilter.h> + +QT_BEGIN_NAMESPACE +class QAction; +class QMenu; +QT_END_NAMESPACE + +namespace Core { +namespace Internal { + +class MenuBarFilter : public ILocatorFilter +{ +public: + MenuBarFilter(); + + QList<LocatorFilterEntry> matchesFor(QFutureInterface<LocatorFilterEntry> &future, + const QString &entry) override; + void accept(LocatorFilterEntry selection, QString *newText, + int *selectionStart, int *selectionLength) const override; + void refresh(QFutureInterface<void> &future) override; + void prepareSearch(const QString &entry) override; +private: + QList<LocatorFilterEntry> matchesForAction(QAction *action, + const QStringList &entryPath, + const QStringList &path, + QVector<const QMenu *> &processedMenus); + +}; + +} // namespace Internal +} // namespace Core diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index 0bc3391ce8..74b1daf63b 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -12,10 +12,8 @@ HEADERS += \ cppeditorenums.h \ cppeditorplugin.h \ cppeditorwidget.h \ - cppelementevaluator.h \ cppfunctiondecldeflink.h \ cpphighlighter.h \ - cpphoverhandler.h \ cppparsecontext.h \ cppincludehierarchy.h \ cppinsertvirtualmethods.h \ @@ -38,10 +36,8 @@ SOURCES += \ cppeditordocument.cpp \ cppeditorplugin.cpp \ cppeditorwidget.cpp \ - cppelementevaluator.cpp \ cppfunctiondecldeflink.cpp \ cpphighlighter.cpp \ - cpphoverhandler.cpp \ cppparsecontext.cpp \ cppincludehierarchy.cpp \ cppinsertvirtualmethods.cpp \ diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index 5d8b17adb4..5a44f175eb 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -39,14 +39,10 @@ QtcPlugin { "cppeditorenums.h", "cppeditorplugin.cpp", "cppeditorplugin.h", - "cppelementevaluator.cpp", - "cppelementevaluator.h", "cppfunctiondecldeflink.cpp", "cppfunctiondecldeflink.h", "cpphighlighter.cpp", "cpphighlighter.h", - "cpphoverhandler.cpp", - "cpphoverhandler.h", "cppincludehierarchy.cpp", "cppincludehierarchy.h", "cppinsertvirtualmethods.cpp", diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp index f168f1810b..3fcbda6a1e 100644 --- a/src/plugins/cppeditor/cppeditordocument.cpp +++ b/src/plugins/cppeditor/cppeditordocument.cpp @@ -394,7 +394,7 @@ const MinimizableInfoBars &CppEditorDocument::minimizableInfoBars() const CppTools::BaseEditorDocumentProcessor *CppEditorDocument::processor() { if (!m_processor) { - m_processor.reset(mm()->editorDocumentProcessor(this)); + m_processor.reset(mm()->createEditorDocumentProcessor(this)); connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::projectPartInfoUpdated, [this] (const CppTools::ProjectPartInfo &info) { diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp index 3f352f1ffe..27cbf4827e 100644 --- a/src/plugins/cppeditor/cppeditorplugin.cpp +++ b/src/plugins/cppeditor/cppeditorplugin.cpp @@ -31,7 +31,6 @@ #include "cppeditorwidget.h" #include "cppeditordocument.h" #include "cpphighlighter.h" -#include "cpphoverhandler.h" #include "cppincludehierarchy.h" #include "cppoutline.h" #include "cppquickfixassistant.h" @@ -53,6 +52,7 @@ #include <coreplugin/icore.h> #include <coreplugin/navigationwidget.h> #include <coreplugin/progressmanager/progressmanager.h> +#include <cpptools/cpphoverhandler.h> #include <cpptools/cpptoolsconstants.h> #include <texteditor/texteditoractionhandler.h> #include <texteditor/texteditorconstants.h> @@ -105,7 +105,7 @@ public: | TextEditorActionHandler::UnCollapseAll | TextEditorActionHandler::FollowSymbolUnderCursor); - addHoverHandler(new CppHoverHandler); + addHoverHandler(CppModelManager::instance()->createHoverHandler()); addHoverHandler(new ColorPreviewHoverHandler); addHoverHandler(new ResourcePreviewHoverHandler); } @@ -145,7 +145,6 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err { Q_UNUSED(errorMessage) - addAutoReleasedObject(new CppEditorFactory); addAutoReleasedObject(new CppOutlineWidgetFactory); addAutoReleasedObject(new CppTypeHierarchyFactory); addAutoReleasedObject(new CppIncludeHierarchyFactory); @@ -268,6 +267,10 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err void CppEditorPlugin::extensionsInitialized() { + // Add the editor factory here instead of in initialize() + // so that the Clang Code Model has a chance to hook in. + addAutoReleasedObject(new CppEditorFactory); + if (!HostOsInfo::isMacHost() && !HostOsInfo::isWindowsHost()) { FileIconProvider::registerIconOverlayForMimeType( QIcon(creatorTheme()->imageFile(Theme::IconOverlayCppSource, QLatin1String(":/cppeditor/images/qt_cpp.png"))), diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp deleted file mode 100644 index d480c12c61..0000000000 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "cpphoverhandler.h" - -#include "cppeditorconstants.h" -#include "cppelementevaluator.h" - -#include <coreplugin/helpmanager.h> -#include <cpptools/baseeditordocumentprocessor.h> -#include <cpptools/cppmodelmanager.h> -#include <cpptools/editordocumenthandle.h> -#include <texteditor/texteditor.h> - -#include <utils/textutils.h> -#include <utils/qtcassert.h> -#include <utils/tooltip/tooltip.h> - -#include <QTextCursor> -#include <QUrl> -#include <QVBoxLayout> - -using namespace Core; -using namespace TextEditor; - -namespace { - -CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(TextEditorWidget *editorWidget) -{ - const QString filePath = editorWidget->textDocument()->filePath().toString(); - auto cppModelManager = CppTools::CppModelManager::instance(); - CppTools::CppEditorDocumentHandle *editorHandle = cppModelManager->cppEditorDocument(filePath); - - if (editorHandle) - return editorHandle->processor(); - - return 0; -} - -bool editorDocumentProcessorHasDiagnosticAt(TextEditorWidget *editorWidget, int pos) -{ - if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) { - int line, column; - if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column)) - return processor->hasDiagnosticsAt(line, column); - } - - return false; -} - -void processWithEditorDocumentProcessor(TextEditorWidget *editorWidget, - const QPoint &point, - int position, - const QString &helpId) -{ - if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) { - int line, column; - if (Utils::Text::convertPosition(editorWidget->document(), position, &line, &column)) { - auto layout = new QVBoxLayout; - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(2); - processor->addDiagnosticToolTipToLayout(line, column, layout); - Utils::ToolTip::show(point, layout, editorWidget, helpId); - } - } -} - -} // anonymous namespace - -namespace CppEditor { -namespace Internal { - -void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos) -{ - m_positionForEditorDocumentProcessor = -1; - - if (editorDocumentProcessorHasDiagnosticAt(editorWidget, pos)) { - setPriority(Priority_Diagnostic); - m_positionForEditorDocumentProcessor = pos; - return; - } - - QTextCursor tc(editorWidget->document()); - tc.setPosition(pos); - - CppElementEvaluator evaluator(editorWidget); - evaluator.setTextCursor(tc); - evaluator.execute(); - if (evaluator.hasDiagnosis()) { - setToolTip(evaluator.diagnosis()); - setPriority(Priority_Diagnostic); - } else if (evaluator.identifiedCppElement()) { - const QSharedPointer<CppElement> &cppElement = evaluator.cppElement(); - if (priority() != Priority_Diagnostic) { - setToolTip(cppElement->tooltip); - setPriority(cppElement->tooltip.isEmpty() ? Priority_None : Priority_Tooltip); - } - QStringList candidates = cppElement->helpIdCandidates; - candidates.removeDuplicates(); - foreach (const QString &helpId, candidates) { - if (helpId.isEmpty()) - continue; - - const QMap<QString, QUrl> helpLinks = HelpManager::linksForIdentifier(helpId); - if (!helpLinks.isEmpty()) { - setLastHelpItemIdentified(HelpItem(helpId, - cppElement->helpMark, - cppElement->helpCategory, - helpLinks)); - break; - } - } - } -} - -void CppHoverHandler::decorateToolTip() -{ - if (m_positionForEditorDocumentProcessor != -1) - return; - - if (Qt::mightBeRichText(toolTip())) - setToolTip(toolTip().toHtmlEscaped()); - - if (priority() != Priority_Diagnostic) - return; - - const HelpItem &help = lastHelpItemIdentified(); - if (help.isValid()) { - // If Qt is built with a namespace, we still show the tip without it, as - // it is in the docs and for consistency with the doc extraction mechanism. - const HelpItem::Category category = help.category(); - const QString &contents = help.extractContent(false); - if (!contents.isEmpty()) { - if (category == HelpItem::ClassOrNamespace) - setToolTip(help.helpId() + contents); - else - setToolTip(contents); - } else if (category == HelpItem::Typedef || - category == HelpItem::Enum || - category == HelpItem::ClassOrNamespace) { - // This approach is a bit limited since it cannot be used for functions - // because the help id doesn't really help in that case. - QString prefix; - if (category == HelpItem::Typedef) - prefix = QLatin1String("typedef "); - else if (category == HelpItem::Enum) - prefix = QLatin1String("enum "); - setToolTip(prefix + help.helpId()); - } - } -} - -void CppHoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget, - const QPoint &point) -{ - if (m_positionForEditorDocumentProcessor == -1) { - BaseHoverHandler::operateTooltip(editorWidget, point); - return; - } - - const HelpItem helpItem = lastHelpItemIdentified(); - const QString helpId = helpItem.isValid() ? helpItem.helpId() : QString(); - processWithEditorDocumentProcessor(editorWidget, point, m_positionForEditorDocumentProcessor, - helpId); -} - -} // namespace Internal -} // namespace CppEditor diff --git a/src/plugins/cppeditor/cppincludehierarchy.cpp b/src/plugins/cppeditor/cppincludehierarchy.cpp index 1f5f089181..22bebf3daf 100644 --- a/src/plugins/cppeditor/cppincludehierarchy.cpp +++ b/src/plugins/cppeditor/cppincludehierarchy.cpp @@ -29,13 +29,13 @@ #include "cppeditorwidget.h" #include "cppeditorconstants.h" #include "cppeditorplugin.h" -#include "cppelementevaluator.h" #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/fileiconprovider.h> #include <coreplugin/find/itemviewfind.h> #include <cpptools/baseeditordocumentprocessor.h> +#include <cpptools/cppelementevaluator.h> #include <cpptools/cppmodelmanager.h> #include <cpptools/cpptoolsbridge.h> #include <cpptools/editordocumenthandle.h> diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp index 54eaaf2f57..0b3198d4c9 100644 --- a/src/plugins/cppeditor/cpptypehierarchy.cpp +++ b/src/plugins/cppeditor/cpptypehierarchy.cpp @@ -28,11 +28,11 @@ #include "cppeditorconstants.h" #include "cppeditor.h" #include "cppeditorwidget.h" -#include "cppelementevaluator.h" #include "cppeditorplugin.h" #include <coreplugin/find/itemviewfind.h> #include <coreplugin/editormanager/editormanager.h> +#include <cpptools/cppelementevaluator.h> #include <utils/algorithm.h> #include <utils/annotateditemdelegate.h> #include <utils/navigationtreeview.h> @@ -46,6 +46,7 @@ #include <QVBoxLayout> using namespace CppEditor; +using namespace CppTools; using namespace CppEditor::Internal; using namespace Utils; diff --git a/src/plugins/cppeditor/cpptypehierarchy.h b/src/plugins/cppeditor/cpptypehierarchy.h index 355f87065d..e99d8a180e 100644 --- a/src/plugins/cppeditor/cpptypehierarchy.h +++ b/src/plugins/cppeditor/cpptypehierarchy.h @@ -47,11 +47,12 @@ class NavigationTreeView; class AnnotatedItemDelegate; } +namespace CppTools { class CppClass; } + namespace CppEditor { namespace Internal { class CppEditorWidget; -class CppClass; class CppTypeHierarchyModel : public QStandardItemModel { @@ -75,8 +76,8 @@ public: void perform(); private: - typedef QList<CppClass> CppClass::*HierarchyMember; - void buildHierarchy(const CppClass &cppClass, QStandardItem *parent, + typedef QList<CppTools::CppClass> CppTools::CppClass::*HierarchyMember; + void buildHierarchy(const CppTools::CppClass &cppClass, QStandardItem *parent, bool isRoot, HierarchyMember member); void showNoTypeHierarchyLabel(); void showTypeHierarchy(); diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 1f7576c49b..ef025a6179 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -27,8 +27,8 @@ #include "cppeditorwidget.h" #include "cppeditorplugin.h" #include "cppeditortestcase.h" -#include "cppelementevaluator.h" +#include <cpptools/cppelementevaluator.h> #include <cpptools/cppfollowsymbolundercursor.h> #include <cpptools/cppvirtualfunctionassistprovider.h> #include <cpptools/cppvirtualfunctionproposalitem.h> diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.cpp b/src/plugins/cpptools/baseeditordocumentprocessor.cpp index 5bffb51a38..20632289c6 100644 --- a/src/plugins/cpptools/baseeditordocumentprocessor.cpp +++ b/src/plugins/cpptools/baseeditordocumentprocessor.cpp @@ -97,6 +97,13 @@ void BaseEditorDocumentProcessor::setParserConfig( parser()->setConfiguration(config); } +QFuture<ToolTipInfo> BaseEditorDocumentProcessor::toolTipInfo(const QByteArray &/*codecName*/, + int /*line*/, + int /*column*/) +{ + return QFuture<ToolTipInfo>(); +} + void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future, BaseEditorDocumentParser::Ptr parser, BaseEditorDocumentParser::UpdateParams updateParams) diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h index b3f96d466d..d799c636b2 100644 --- a/src/plugins/cpptools/baseeditordocumentprocessor.h +++ b/src/plugins/cpptools/baseeditordocumentprocessor.h @@ -32,6 +32,7 @@ #include "cpptools_global.h" #include <texteditor/codeassist/assistinterface.h> +#include <texteditor/helpitem.h> #include <texteditor/quickfix.h> #include <texteditor/texteditor.h> #include <texteditor/textdocument.h> @@ -48,6 +49,18 @@ class TextDocument; namespace CppTools { +// For clang code model only, move? +struct CPPTOOLS_EXPORT ToolTipInfo { + QString text; + QString briefComment; + + QStringList qDocIdCandidates; + QString qDocMark; + TextEditor::HelpItem::Category qDocCategory; + + QString sizeInBytes; +}; + class CPPTOOLS_EXPORT BaseEditorDocumentProcessor : public QObject { Q_OBJECT @@ -78,6 +91,7 @@ public: virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams ¶ms) = 0; virtual QFuture<CursorInfo> requestLocalReferences(const QTextCursor &cursor) = 0; virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0; + virtual QFuture<ToolTipInfo> toolTipInfo(const QByteArray &codecName, int line, int column); public: using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>; diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cpptools/cppelementevaluator.cpp index 1e95850a18..3281783ef2 100644 --- a/src/plugins/cppeditor/cppelementevaluator.cpp +++ b/src/plugins/cpptools/cppelementevaluator.cpp @@ -42,8 +42,7 @@ using namespace CPlusPlus; -namespace CppEditor { -namespace Internal { +namespace CppTools { static QStringList stripName(const QString &name) { @@ -471,5 +470,4 @@ CppEnumerator::CppEnumerator(EnumeratorDeclaration *declaration) tooltip.append(QLatin1String(" = ") + enumeratorValue); } -} // namespace Internal -} // namespace CppEditor +} // namespace CppTools diff --git a/src/plugins/cppeditor/cppelementevaluator.h b/src/plugins/cpptools/cppelementevaluator.h index 91ef68e2d8..af994989ed 100644 --- a/src/plugins/cppeditor/cppelementevaluator.h +++ b/src/plugins/cpptools/cppelementevaluator.h @@ -25,6 +25,8 @@ #pragma once +#include "cpptools_global.h" + #include <texteditor/texteditor.h> #include <texteditor/helpitem.h> @@ -41,14 +43,11 @@ class LookupItem; class LookupContext; } -namespace CppTools { class CppModelManager; } - -namespace CppEditor { -namespace Internal { - +namespace CppTools { class CppElement; +class CppModelManager; -class CppElementEvaluator +class CPPTOOLS_EXPORT CppElementEvaluator { public: explicit CppElementEvaluator(TextEditor::TextEditorWidget *editor); @@ -82,7 +81,7 @@ private: QString m_diagnosis; }; -class CppElement +class CPPTOOLS_EXPORT CppElement { protected: CppElement(); @@ -189,5 +188,4 @@ public: explicit CppEnumerator(CPlusPlus::EnumeratorDeclaration *declaration); }; -} // namespace Internal -} // namespace CppEditor +} // namespace CppTools diff --git a/src/plugins/cpptools/cpphoverhandler.cpp b/src/plugins/cpptools/cpphoverhandler.cpp new file mode 100644 index 0000000000..1ff41b7fdc --- /dev/null +++ b/src/plugins/cpptools/cpphoverhandler.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "cpphoverhandler.h" + +#include "cppelementevaluator.h" + +#include <coreplugin/helpmanager.h> +#include <texteditor/texteditor.h> + +#include <utils/textutils.h> + +#include <QTextCursor> +#include <QUrl> + +using namespace Core; +using namespace TextEditor; + +namespace CppTools { + +QString CppHoverHandler::tooltipTextForHelpItem(const HelpItem &helpItem) +{ + // If Qt is built with a namespace, we still show the tip without it, as + // it is in the docs and for consistency with the doc extraction mechanism. + const HelpItem::Category category = helpItem.category(); + const QString &contents = helpItem.extractContent(false); + if (!contents.isEmpty()) { + if (category == HelpItem::ClassOrNamespace) + return helpItem.helpId() + contents; + else + return contents; + } else if (category == HelpItem::Typedef || + category == HelpItem::Enum || + category == HelpItem::ClassOrNamespace) { + // This approach is a bit limited since it cannot be used for functions + // because the help id doesn't really help in that case. + QString prefix; + if (category == HelpItem::Typedef) + prefix = QLatin1String("typedef "); + else if (category == HelpItem::Enum) + prefix = QLatin1String("enum "); + return prefix + helpItem.helpId(); + } + + return QString(); +} + +void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos) +{ + QTextCursor tc(editorWidget->document()); + tc.setPosition(pos); + + CppElementEvaluator evaluator(editorWidget); + evaluator.setTextCursor(tc); + evaluator.execute(); + if (evaluator.hasDiagnosis()) { + setToolTip(evaluator.diagnosis()); + setPriority(Priority_Diagnostic); + } else if (evaluator.identifiedCppElement()) { + const QSharedPointer<CppElement> &cppElement = evaluator.cppElement(); + if (priority() != Priority_Diagnostic) { + setToolTip(cppElement->tooltip); + setPriority(cppElement->tooltip.isEmpty() ? Priority_None : Priority_Tooltip); + } + QStringList candidates = cppElement->helpIdCandidates; + candidates.removeDuplicates(); + foreach (const QString &helpId, candidates) { + if (helpId.isEmpty()) + continue; + + const QMap<QString, QUrl> helpLinks = HelpManager::linksForIdentifier(helpId); + if (!helpLinks.isEmpty()) { + setLastHelpItemIdentified(HelpItem(helpId, + cppElement->helpMark, + cppElement->helpCategory, + helpLinks)); + break; + } + } + } +} + +void CppHoverHandler::decorateToolTip() +{ + if (Qt::mightBeRichText(toolTip())) + setToolTip(toolTip().toHtmlEscaped()); + + if (priority() == Priority_Diagnostic) + return; + + const HelpItem &help = lastHelpItemIdentified(); + if (help.isValid()) { + const QString text = tooltipTextForHelpItem(help); + if (!text.isEmpty()) + setToolTip(text); + } +} + +} // namespace CppTools diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cpptools/cpphoverhandler.h index accc275152..edfa6901cf 100644 --- a/src/plugins/cppeditor/cpphoverhandler.h +++ b/src/plugins/cpptools/cpphoverhandler.h @@ -25,21 +25,20 @@ #pragma once +#include "cpptools_global.h" + #include <texteditor/basehoverhandler.h> -namespace CppEditor { -namespace Internal { +namespace CppTools { -class CppHoverHandler : public TextEditor::BaseHoverHandler +class CPPTOOLS_EXPORT CppHoverHandler : public TextEditor::BaseHoverHandler { +public: + static QString tooltipTextForHelpItem(const TextEditor::HelpItem &help); + private: void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos) override; void decorateToolTip() override; - void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override; - -private: - int m_positionForEditorDocumentProcessor = -1; }; -} // namespace Internal -} // namespace CppEditor +} // namespace CppTools diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index ad255459b2..f1b1d2c2bd 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -1293,10 +1293,15 @@ CppCompletionAssistProvider *CppModelManager::completionAssistProvider() const return d->m_activeModelManagerSupport->completionAssistProvider(); } -BaseEditorDocumentProcessor *CppModelManager::editorDocumentProcessor( - TextEditor::TextDocument *baseTextDocument) const +TextEditor::BaseHoverHandler *CppModelManager::createHoverHandler() const { - return d->m_activeModelManagerSupport->editorDocumentProcessor(baseTextDocument); + return d->m_activeModelManagerSupport->createHoverHandler(); +} + +BaseEditorDocumentProcessor *CppModelManager::createEditorDocumentProcessor( + TextEditor::TextDocument *baseTextDocument) const +{ + return d->m_activeModelManagerSupport->createEditorDocumentProcessor(baseTextDocument); } void CppModelManager::setIndexingSupport(CppIndexingSupport *indexingSupport) diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 3eb06eca65..d8b8d2f192 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -44,7 +44,10 @@ class IEditor; } namespace CPlusPlus { class LookupContext; } namespace ProjectExplorer { class Project; } -namespace TextEditor { class TextDocument; } +namespace TextEditor { +class BaseHoverHandler; +class TextDocument; +} // namespace TextEditor namespace CppTools { @@ -172,8 +175,9 @@ public: void activateClangCodeModel(ModelManagerSupportProvider *modelManagerSupportProvider); CppCompletionAssistProvider *completionAssistProvider() const; - BaseEditorDocumentProcessor *editorDocumentProcessor( - TextEditor::TextDocument *baseTextDocument) const; + BaseEditorDocumentProcessor *createEditorDocumentProcessor( + TextEditor::TextDocument *baseTextDocument) const; + TextEditor::BaseHoverHandler *createHoverHandler() const; FollowSymbolInterface &followSymbolInterface() const; void setIndexingSupport(CppIndexingSupport *indexingSupport); diff --git a/src/plugins/cpptools/cppmodelmanagersupport.h b/src/plugins/cpptools/cppmodelmanagersupport.h index b1256aa51f..06102f6007 100644 --- a/src/plugins/cpptools/cppmodelmanagersupport.h +++ b/src/plugins/cpptools/cppmodelmanagersupport.h @@ -30,7 +30,10 @@ #include <QSharedPointer> #include <QString> -namespace TextEditor { class TextDocument; } +namespace TextEditor { +class TextDocument; +class BaseHoverHandler; +} // namespace TextEditor namespace CppTools { @@ -48,7 +51,8 @@ public: virtual ~ModelManagerSupport() = 0; virtual CppCompletionAssistProvider *completionAssistProvider() = 0; - virtual BaseEditorDocumentProcessor *editorDocumentProcessor( + virtual TextEditor::BaseHoverHandler *createHoverHandler() = 0; + virtual BaseEditorDocumentProcessor *createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) = 0; virtual FollowSymbolInterface &followSymbolInterface() = 0; virtual RefactoringEngineInterface &refactoringEngineInterface() = 0; diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp index 95b98bbdf3..5191995554 100644 --- a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp +++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp @@ -26,6 +26,7 @@ #include "cppcompletionassist.h" #include "cppmodelmanagersupportinternal.h" #include "cppfollowsymbolundercursor.h" +#include "cpphoverhandler.h" #include "cpprefactoringengine.h" #include "builtineditordocumentprocessor.h" @@ -63,7 +64,7 @@ ModelManagerSupportInternal::~ModelManagerSupportInternal() { } -BaseEditorDocumentProcessor *ModelManagerSupportInternal::editorDocumentProcessor( +BaseEditorDocumentProcessor *ModelManagerSupportInternal::createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) { return new BuiltinEditorDocumentProcessor(baseTextDocument); @@ -74,6 +75,11 @@ CppCompletionAssistProvider *ModelManagerSupportInternal::completionAssistProvid return m_completionAssistProvider.data(); } +TextEditor::BaseHoverHandler *ModelManagerSupportInternal::createHoverHandler() +{ + return new CppHoverHandler; +} + FollowSymbolInterface &ModelManagerSupportInternal::followSymbolInterface() { return *m_followSymbol; diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.h b/src/plugins/cpptools/cppmodelmanagersupportinternal.h index 6ac2d4d022..e2954792ea 100644 --- a/src/plugins/cpptools/cppmodelmanagersupportinternal.h +++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.h @@ -41,7 +41,8 @@ public: virtual ~ModelManagerSupportInternal(); CppCompletionAssistProvider *completionAssistProvider() final; - BaseEditorDocumentProcessor *editorDocumentProcessor( + TextEditor::BaseHoverHandler *createHoverHandler() final; + BaseEditorDocumentProcessor *createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) final; FollowSymbolInterface &followSymbolInterface() final; RefactoringEngineInterface &refactoringEngineInterface() final; diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index 4dfc0ceece..e16e3ec0bc 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -32,11 +32,13 @@ HEADERS += \ cppdoxygen.h \ cppeditoroutline.h \ cppeditorwidgetinterface.h \ + cppelementevaluator.h \ cppfileiterationorder.h \ cppfilesettingspage.h \ cppfindreferences.h \ cppfollowsymbolundercursor.h \ cppfunctionsfilter.h \ + cpphoverhandler.h \ cppincludesfilter.h \ cppindexingsupport.h \ cpplocalsymbols.h \ @@ -125,11 +127,13 @@ SOURCES += \ cppcurrentdocumentfilter.cpp \ cppeditoroutline.cpp \ cppdoxygen.cpp \ + cppelementevaluator.cpp \ cppfileiterationorder.cpp \ cppfilesettingspage.cpp \ cppfindreferences.cpp \ cppfollowsymbolundercursor.cpp \ cppfunctionsfilter.cpp \ + cpphoverhandler.cpp \ cppincludesfilter.cpp \ cppindexingsupport.cpp \ cpplocalsymbols.cpp \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index a510f5a21d..a258ce18a3 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -90,6 +90,8 @@ Project { "cppeditoroutline.cpp", "cppeditoroutline.h", "cppeditorwidgetinterface.h", + "cppelementevaluator.cpp", + "cppelementevaluator.h", "cppfileiterationorder.cpp", "cppfileiterationorder.h", "cppfilesettingspage.cpp", @@ -101,6 +103,8 @@ Project { "cppfollowsymbolundercursor.h", "cppfunctionsfilter.cpp", "cppfunctionsfilter.h", + "cpphoverhandler.cpp", + "cpphoverhandler.h", "cppincludesfilter.cpp", "cppincludesfilter.h", "cppindexingsupport.cpp", diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index a71127e38f..e0fa782c39 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -3179,7 +3179,8 @@ QWidget *mainWindow() void raiseWatchersWindow() { - return dd->m_mainWindow->raiseDock(DOCKWIDGET_WATCHERS); + if (currentEngine()->state() != DebuggerNotReady) + dd->m_mainWindow->raiseDock(DOCKWIDGET_WATCHERS); } bool isRegistersWindowVisible() diff --git a/src/plugins/modeleditor/componentviewcontroller.cpp b/src/plugins/modeleditor/componentviewcontroller.cpp index 1c35e91202..52501649cd 100644 --- a/src/plugins/modeleditor/componentviewcontroller.cpp +++ b/src/plugins/modeleditor/componentviewcontroller.cpp @@ -133,6 +133,7 @@ private: private: qmt::ModelController *m_modelController = nullptr; QMultiHash<QString, Node> m_filePaths; + QHash<QString, qmt::MComponent *> m_filePathComponentsMap; }; void UpdateIncludeDependenciesVisitor::setModelController(qmt::ModelController *modelController) @@ -161,6 +162,16 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen if (document) { foreach (const CPlusPlus::Document::Include &include, document->resolvedIncludes()) { QString includeFilePath = include.resolvedFileName(); + // replace proxy header with real one + CPlusPlus::Document::Ptr includeDocument = snapshot.document(includeFilePath); + if (includeDocument) { + QList<CPlusPlus::Document::Include> includes = includeDocument->resolvedIncludes(); + if (includes.count() == 1 && + QFileInfo(includes.at(0).resolvedFileName()).fileName() == QFileInfo(includeFilePath).fileName()) + { + includeFilePath = includes.at(0).resolvedFileName(); + } + } qmt::MComponent *includeComponent = findComponentFromFilePath(includeFilePath); if (includeComponent && includeComponent != component) { // add dependency between components @@ -312,10 +323,16 @@ void UpdateIncludeDependenciesVisitor::collectElementPaths(const ProjectExplorer qmt::MComponent *UpdateIncludeDependenciesVisitor::findComponentFromFilePath(const QString &filePath) { + const auto it = m_filePathComponentsMap.find(filePath); + if (it != m_filePathComponentsMap.cend()) + return it.value(); + FindComponentFromFilePath visitor; visitor.setFilePath(filePath); m_modelController->rootPackage()->accept(&visitor); - return visitor.component(); + qmt::MComponent *component = visitor.component(); + m_filePathComponentsMap.insert(filePath, component); + return component; } bool UpdateIncludeDependenciesVisitor::haveDependency(const qmt::MObject *source, @@ -390,7 +407,8 @@ void ComponentViewController::createComponentModel(const QString &filePath, const QString &anchorFolder) { d->diagramSceneController->modelController()->startResetModel(); - doCreateComponentModel(filePath, diagram, anchorFolder); + doCreateComponentModel(filePath, diagram, anchorFolder, false); + doCreateComponentModel(filePath, diagram, anchorFolder, true); d->diagramSceneController->modelController()->finishResetModel(true); } @@ -404,7 +422,8 @@ void ComponentViewController::updateIncludeDependencies(qmt::MPackage *rootPacka d->diagramSceneController->modelController()->finishResetModel(true); } -void ComponentViewController::doCreateComponentModel(const QString &filePath, qmt::MDiagram *diagram, const QString &anchorFolder) +void ComponentViewController::doCreateComponentModel(const QString &filePath, qmt::MDiagram *diagram, + const QString &anchorFolder, bool scanHeaders) { for (const QString &fileName : QDir(filePath).entryList(QDir::Files)) { QString file = filePath + "/" + fileName; @@ -413,18 +432,20 @@ void ComponentViewController::doCreateComponentModel(const QString &filePath, qm bool isSource = false; CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(file); switch (kind) { - case CppTools::ProjectFile::AmbiguousHeader: - case CppTools::ProjectFile::CHeader: case CppTools::ProjectFile::CSource: - case CppTools::ProjectFile::CXXHeader: case CppTools::ProjectFile::CXXSource: case CppTools::ProjectFile::ObjCSource: - case CppTools::ProjectFile::ObjCHeader: case CppTools::ProjectFile::ObjCXXSource: - case CppTools::ProjectFile::ObjCXXHeader: case CppTools::ProjectFile::CudaSource: case CppTools::ProjectFile::OpenCLSource: - isSource = true; + isSource = !scanHeaders; + break; + case CppTools::ProjectFile::AmbiguousHeader: + case CppTools::ProjectFile::CHeader: + case CppTools::ProjectFile::CXXHeader: + case CppTools::ProjectFile::ObjCHeader: + case CppTools::ProjectFile::ObjCXXHeader: + isSource = scanHeaders && !isProxyHeader(file); break; case CppTools::ProjectFile::Unclassified: case CppTools::ProjectFile::Unsupported: @@ -450,9 +471,24 @@ void ComponentViewController::doCreateComponentModel(const QString &filePath, qm } for (const QString &fileName : QDir(filePath).entryList(QDir::Dirs|QDir::NoDotAndDotDot)) { QString file = filePath + "/" + fileName; - doCreateComponentModel(file, diagram, anchorFolder); + doCreateComponentModel(file, diagram, anchorFolder, scanHeaders); } } +bool ComponentViewController::isProxyHeader(const QString &file) const +{ + CppTools::CppModelManager *cppModelManager = CppTools::CppModelManager::instance(); + CPlusPlus::Snapshot snapshot = cppModelManager->snapshot(); + + CPlusPlus::Document::Ptr document = snapshot.document(file); + if (document) { + QList<CPlusPlus::Document::Include> includes = document->resolvedIncludes(); + if (includes.count() != 1) + return false; + return QFileInfo(includes.at(0).resolvedFileName()).fileName() == QFileInfo(file).fileName(); + } + return false; +} + } // namespace Internal } // namespace ModelEditor diff --git a/src/plugins/modeleditor/componentviewcontroller.h b/src/plugins/modeleditor/componentviewcontroller.h index 98f4ac0ca6..584bc55b50 100644 --- a/src/plugins/modeleditor/componentviewcontroller.h +++ b/src/plugins/modeleditor/componentviewcontroller.h @@ -58,8 +58,9 @@ public: void updateIncludeDependencies(qmt::MPackage *rootPackage); private: - void doCreateComponentModel(const QString &filePath, - qmt::MDiagram *diagram, const QString &anchorFolder); + void doCreateComponentModel(const QString &filePath, qmt::MDiagram *diagram, + const QString &anchorFolder, bool scanHeaders); + bool isProxyHeader(const QString &file) const; ComponentViewControllerPrivate *d; }; diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index d8806023fb..f2286bdc3c 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -382,15 +382,15 @@ QString BaseQtVersion::defaultUnexpandedDisplayName(const FileName &qmakePath, b QDir dir = qmakePath.toFileInfo().absoluteDir(); do { const QString dirName = dir.dirName(); - if (dirName == QLatin1String("usr")) { // System-installed Qt. + if (dirName == "usr") { // System-installed Qt. location = QCoreApplication::translate("QtVersion", "System"); break; } location = dirName; // Also skip default checkouts named 'qt'. Parent dir might have descriptive name. - if (dirName.compare(QLatin1String("bin"), Qt::CaseInsensitive) - && dirName.compare(QLatin1String("qtbase"), Qt::CaseInsensitive) - && dirName.compare(QLatin1String("qt"), Qt::CaseInsensitive)) { + if (dirName.compare("bin", Qt::CaseInsensitive) + && dirName.compare("qtbase", Qt::CaseInsensitive) + && dirName.compare("qt", Qt::CaseInsensitive)) { break; } } while (!dir.isRoot() && dir.cdUp()); @@ -527,7 +527,7 @@ QList<Task> BaseQtVersion::validateKit(const Kit *k) QString qtAbiString; foreach (const Abi &qtAbi, qtAbis) { if (!qtAbiString.isEmpty()) - qtAbiString.append(QLatin1Char(' ')); + qtAbiString.append(' '); qtAbiString.append(qtAbi.toString()); if (!fullMatch) @@ -589,13 +589,13 @@ FileName BaseQtVersion::mkspecsPath() const if (result.isEmpty()) result = FileName::fromUserInput(qmakeProperty("QMAKE_MKSPECS")); else - result.appendPath(QLatin1String("mkspecs")); + result.appendPath("mkspecs"); return result; } FileName BaseQtVersion::qmlBinPath() const { - return FileName::fromUserInput(m_mkspecValues.value(QLatin1String("QT.qml.bins"))); + return FileName::fromUserInput(m_mkspecValues.value("QT.qml.bins")); } FileName BaseQtVersion::librarySearchPath() const @@ -623,13 +623,13 @@ FileNameList BaseQtVersion::directoriesToIgnoreInProjectTree() const QString BaseQtVersion::qtNamespace() const { ensureMkSpecParsed(); - return m_mkspecValues.value(QLatin1String(MKSPEC_VALUE_NAMESPACE)); + return m_mkspecValues.value(MKSPEC_VALUE_NAMESPACE); } QString BaseQtVersion::qtLibInfix() const { ensureMkSpecParsed(); - return m_mkspecValues.value(QLatin1String(MKSPEC_VALUE_LIBINFIX)); + return m_mkspecValues.value(MKSPEC_VALUE_LIBINFIX); } bool BaseQtVersion::isFrameworkBuild() const @@ -655,15 +655,15 @@ void BaseQtVersion::setId(int id) void BaseQtVersion::fromMap(const QVariantMap &map) { - m_id = map.value(QLatin1String(Constants::QTVERSIONID)).toInt(); + m_id = map.value(Constants::QTVERSIONID).toInt(); if (m_id == -1) // this happens on adding from installer, see updateFromInstaller => get a new unique id m_id = QtVersionManager::getUniqueId(); - m_unexpandedDisplayName = map.value(QLatin1String(Constants::QTVERSIONNAME)).toString(); - m_isAutodetected = map.value(QLatin1String(QTVERSIONAUTODETECTED)).toBool(); + m_unexpandedDisplayName = map.value(Constants::QTVERSIONNAME).toString(); + m_isAutodetected = map.value(QTVERSIONAUTODETECTED).toBool(); if (m_isAutodetected) - m_autodetectionSource = map.value(QLatin1String(QTVERSIONAUTODETECTIONSOURCE)).toString(); - QString string = map.value(QLatin1String(QTVERSIONQMAKEPATH)).toString(); - if (string.startsWith(QLatin1Char('~'))) + m_autodetectionSource = map.value(QTVERSIONAUTODETECTIONSOURCE).toString(); + QString string = map.value(QTVERSIONQMAKEPATH).toString(); + if (string.startsWith('~')) string.remove(0, 1).prepend(QDir::homePath()); m_qtSources = Utils::FileName::fromUserInput( @@ -683,12 +683,12 @@ void BaseQtVersion::fromMap(const QVariantMap &map) QVariantMap BaseQtVersion::toMap() const { QVariantMap result; - result.insert(QLatin1String(Constants::QTVERSIONID), uniqueId()); - result.insert(QLatin1String(Constants::QTVERSIONNAME), unexpandedDisplayName()); - result.insert(QLatin1String(QTVERSIONAUTODETECTED), isAutodetected()); + result.insert(Constants::QTVERSIONID, uniqueId()); + result.insert(Constants::QTVERSIONNAME, unexpandedDisplayName()); + result.insert(QTVERSIONAUTODETECTED, isAutodetected()); if (isAutodetected()) - result.insert(QLatin1String(QTVERSIONAUTODETECTIONSOURCE), autodetectionSource()); - result.insert(QLatin1String(QTVERSIONQMAKEPATH), qmakeCommand().toString()); + result.insert(QTVERSIONAUTODETECTIONSOURCE, autodetectionSource()); + result.insert(QTVERSIONQMAKEPATH, qmakeCommand().toString()); return result; } @@ -858,16 +858,16 @@ QString BaseQtVersion::toHtml(bool verbose) const foreach (const ProKey &key, keys) { const QString &value = vInfo.value(key).toQString(); QString variableName = key.toQString(); - if (variableName != QLatin1String("QMAKE_MKSPECS") - && !variableName.endsWith(QLatin1String("/raw"))) { + if (variableName != "QMAKE_MKSPECS" + && !variableName.endsWith("/raw")) { bool isPath = false; - if (variableName.contains(QLatin1String("_HOST_")) - || variableName.contains(QLatin1String("_INSTALL_"))) { - if (!variableName.endsWith(QLatin1String("/get"))) + if (variableName.contains("_HOST_") + || variableName.contains("_INSTALL_")) { + if (!variableName.endsWith("/get")) continue; variableName.chop(4); isPath = true; - } else if (variableName == QLatin1String("QT_SYSROOT")) { + } else if (variableName == "QT_SYSROOT") { isPath = true; } str << "<tr><td><pre>" << variableName << "</pre></td><td>"; @@ -946,7 +946,7 @@ QString BaseQtVersion::findHostBinary(HostBinaries binary) const switch (binary) { case Designer: case Linguist: - baseDir = m_mkspecValues.value(QLatin1String("QT.designer.bins")); + baseDir = m_mkspecValues.value("QT.designer.bins"); break; case Uic: case QScxmlc: @@ -960,33 +960,32 @@ QString BaseQtVersion::findHostBinary(HostBinaries binary) const if (baseDir.isEmpty()) return QString(); - if (!baseDir.endsWith(QLatin1Char('/'))) - baseDir += QLatin1Char('/'); + if (!baseDir.endsWith('/')) + baseDir += '/'; QStringList possibleCommands; switch (binary) { case Designer: if (HostOsInfo::isMacHost()) - possibleCommands << QLatin1String("Designer.app/Contents/MacOS/Designer"); + possibleCommands << "Designer.app/Contents/MacOS/Designer"; else - possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("designer")); + possibleCommands << HostOsInfo::withExecutableSuffix("designer"); break; case Linguist: if (HostOsInfo::isMacHost()) - possibleCommands << QLatin1String("Linguist.app/Contents/MacOS/Linguist"); + possibleCommands << "Linguist.app/Contents/MacOS/Linguist"; else - possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("linguist")); + possibleCommands << HostOsInfo::withExecutableSuffix("linguist"); break; case Uic: if (HostOsInfo::isWindowsHost()) { - possibleCommands << QLatin1String("uic.exe"); + possibleCommands << "uic.exe"; } else { - possibleCommands << QLatin1String("uic-qt4") << QLatin1String("uic4") - << QLatin1String("uic"); + possibleCommands << "uic-qt4" << "uic4" << "uic"; } break; case QScxmlc: - possibleCommands << HostOsInfo::withExecutableSuffix(QLatin1String("qscxmlc")); + possibleCommands << HostOsInfo::withExecutableSuffix("qscxmlc"); break; default: Q_ASSERT(false); @@ -1027,7 +1026,7 @@ void BaseQtVersion::updateMkspec() const m_mkspec = m_mkspec.relativeChildPath(baseMkspecDir); // qDebug() << "Setting mkspec to"<<mkspec; } else { - FileName sourceMkSpecPath = sourcePath().appendPath(QLatin1String("mkspecs")); + FileName sourceMkSpecPath = sourcePath().appendPath("mkspecs"); if (m_mkspec.isChildOf(sourceMkSpecPath)) { m_mkspec = m_mkspec.relativeChildPath(sourceMkSpecPath); } else { @@ -1062,25 +1061,25 @@ void BaseQtVersion::ensureMkSpecParsed() const void BaseQtVersion::parseMkSpec(ProFileEvaluator *evaluator) const { - m_configValues = evaluator->values(QLatin1String("CONFIG")); - m_qtConfigValues = evaluator->values(QLatin1String("QT_CONFIG")); + m_configValues = evaluator->values("CONFIG"); + m_qtConfigValues = evaluator->values("QT_CONFIG"); m_defaultConfigIsDebugAndRelease = false; m_frameworkBuild = false; foreach (const QString &value, m_configValues) { - if (value == QLatin1String("debug")) + if (value == "debug") m_defaultConfigIsDebug = true; - else if (value == QLatin1String("release")) + else if (value == "release") m_defaultConfigIsDebug = false; - else if (value == QLatin1String("build_all")) + else if (value == "build_all") m_defaultConfigIsDebugAndRelease = true; - else if (value == QLatin1String("qt_framework")) + else if (value == "qt_framework") m_frameworkBuild = true; } - const QString designerBins = QLatin1String("QT.designer.bins"); - const QString qmlBins = QLatin1String("QT.qml.bins"); - const QString declarativeBins = QLatin1String("QT.declarative.bins"); - const QString libinfix = QLatin1String(MKSPEC_VALUE_LIBINFIX); - const QString ns = QLatin1String(MKSPEC_VALUE_NAMESPACE); + const QString designerBins = "QT.designer.bins"; + const QString qmlBins = "QT.qml.bins"; + const QString declarativeBins = "QT.declarative.bins"; + const QString libinfix = MKSPEC_VALUE_LIBINFIX; + const QString ns = MKSPEC_VALUE_NAMESPACE; m_mkspecValues.insert(designerBins, evaluator->value(designerBins)); m_mkspecValues.insert(qmlBins, evaluator->value(qmlBins)); m_mkspecValues.insert(declarativeBins, evaluator->value(declarativeBins)); @@ -1123,11 +1122,11 @@ bool BaseQtVersion::hasMkspec(const FileName &spec) const return true; // default spec of a Qt version QDir mkspecDir = QDir(QDir::fromNativeSeparators(qmakeProperty("QT_HOST_DATA")) - + QLatin1String("/mkspecs/")); + + "/mkspecs/"); const QString absSpec = mkspecDir.absoluteFilePath(spec.toString()); if (QFileInfo(absSpec).isDir() && QFileInfo(absSpec + "/qmake.conf").isFile()) return true; - mkspecDir.setPath(sourcePath().toString() + QLatin1String("/mkspecs/")); + mkspecDir.setPath(sourcePath().toString() + "/mkspecs/"); const QString absSrcSpec = mkspecDir.absoluteFilePath(spec.toString()); return absSrcSpec != absSpec && QFileInfo(absSrcSpec).isDir() @@ -1239,7 +1238,7 @@ QString BaseQtVersion::qmakeProperty(const QHash<ProKey,ProString> &versionInfo, variant == PropertyVariantGet ? "/get" : "/src")))).toQString(); if (!val.isNull()) return val; - return versionInfo.value(ProKey(QString::fromLatin1(name))).toQString(); + return versionInfo.value(ProKey(name)).toQString(); } QString BaseQtVersion::qmakeProperty(const QByteArray &name, PropertyVariant variant) const @@ -1363,7 +1362,7 @@ void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Tar void BaseQtVersion::addToEnvironment(const Kit *k, Environment &env) const { Q_UNUSED(k); - env.set(QLatin1String("QTDIR"), QDir::toNativeSeparators(qmakeProperty("QT_HOST_DATA"))); + env.set("QTDIR", QDir::toNativeSeparators(qmakeProperty("QT_HOST_DATA"))); } // Some Qt versions may require environment settings for qmake to work @@ -1454,7 +1453,7 @@ static QByteArray runQmakeQuery(const FileName &binary, const Environment &env, QProcess process; process.setEnvironment(env.toStringList()); - process.start(binary.toString(), QStringList(QLatin1String("-query")), QIODevice::ReadOnly); + process.start(binary.toString(), QStringList("-query"), QIODevice::ReadOnly); if (!process.waitForStarted()) { *error = QCoreApplication::translate("QtVersion", "Cannot start \"%1\": %2").arg(binary.toUserOutput()).arg(process.errorString()); @@ -1521,7 +1520,7 @@ FileName BaseQtVersion::mkspecDirectoryFromVersionInfo(const QHash<ProKey, ProSt QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", PropertyVariantSrc); if (dataDir.isEmpty()) return FileName(); - return FileName::fromUserInput(dataDir + QLatin1String("/mkspecs")); + return FileName::fromUserInput(dataDir + "/mkspecs"); } FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo) @@ -1533,7 +1532,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve bool qt5 = false; QString theSpec = qmakeProperty(versionInfo, "QMAKE_XSPEC"); if (theSpec.isEmpty()) - theSpec = QLatin1String("default"); + theSpec = "default"; else qt5 = true; @@ -1544,7 +1543,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve if (HostOsInfo::isWindowsHost()) { if (!qt5) { - QFile f2(mkspecFullPath.toString() + QLatin1String("/qmake.conf")); + QFile f2(mkspecFullPath.toString() + "/qmake.conf"); if (f2.exists() && f2.open(QIODevice::ReadOnly)) { while (!f2.atEnd()) { QByteArray line = f2.readLine(); @@ -1552,16 +1551,16 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve const QList<QByteArray> &temp = line.split('='); if (temp.size() == 2) { QString possibleFullPath = QString::fromLocal8Bit(temp.at(1).trimmed().constData()); - if (possibleFullPath.contains(QLatin1Char('$'))) { // QTBUG-28792 - const QRegularExpression rex(QLatin1String("\\binclude\\(([^)]+)/qmake\\.conf\\)")); + if (possibleFullPath.contains('$')) { // QTBUG-28792 + const QRegularExpression rex("\\binclude\\(([^)]+)/qmake\\.conf\\)"); const QRegularExpressionMatch match = rex.match(QString::fromLocal8Bit(f2.readAll())); if (match.hasMatch()) { - possibleFullPath = mkspecFullPath.toString() + QLatin1Char('/') + possibleFullPath = mkspecFullPath.toString() + '/' + match.captured(1); } } // We sometimes get a mix of different slash styles here... - possibleFullPath = possibleFullPath.replace(QLatin1Char('\\'), QLatin1Char('/')); + possibleFullPath = possibleFullPath.replace('\\', '/'); if (QFileInfo::exists(possibleFullPath)) // Only if the path exists mkspecFullPath = FileName::fromUserInput(possibleFullPath); } @@ -1573,7 +1572,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve } } else { if (HostOsInfo::isMacHost()) { - QFile f2(mkspecFullPath.toString() + QLatin1String("/qmake.conf")); + QFile f2(mkspecFullPath.toString() + "/qmake.conf"); if (f2.exists() && f2.open(QIODevice::ReadOnly)) { while (!f2.atEnd()) { QByteArray line = f2.readLine(); @@ -1584,7 +1583,7 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash<ProKey, ProString> &ve if (value.contains("XCODE")) { // we don't want to generate xcode projects... // qDebug() << "default mkspec is xcode, falling back to g++"; - return baseMkspecDir.appendPath(QLatin1String("macx-g++")); + return baseMkspecDir.appendPath("macx-g++"); } } break; @@ -1612,14 +1611,14 @@ FileName BaseQtVersion::sourcePath(const QHash<ProKey, ProString> &versionInfo) const QString installData = qmakeProperty(versionInfo, "QT_INSTALL_PREFIX"); QString sourcePath = installData; - QFile qmakeCache(installData + QLatin1String("/.qmake.cache")); + QFile qmakeCache(installData + "/.qmake.cache"); if (qmakeCache.exists() && qmakeCache.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream stream(&qmakeCache); while (!stream.atEnd()) { QString line = stream.readLine().trimmed(); - if (line.startsWith(QLatin1String("QT_SOURCE_TREE"))) { - sourcePath = line.split(QLatin1Char('=')).at(1).trimmed(); - if (sourcePath.startsWith(QLatin1String("$$quote("))) { + if (line.startsWith("QT_SOURCE_TREE")) { + sourcePath = line.split('=').at(1).trimmed(); + if (sourcePath.startsWith("$$quote(")) { sourcePath.remove(0, 8); sourcePath.chop(1); } @@ -1636,7 +1635,7 @@ bool BaseQtVersion::isInSourceDirectory(const Utils::FileName &filePath) if (source.isEmpty()) return false; QDir dir = QDir(source.toString()); - if (dir.dirName() == QLatin1String("qtbase")) + if (dir.dirName() == "qtbase") dir.cdUp(); return filePath.isChildOf(dir); } @@ -1646,7 +1645,7 @@ bool BaseQtVersion::isSubProject(const Utils::FileName &filePath) const const Utils::FileName &source = sourcePath(); if (!source.isEmpty()) { QDir dir = QDir(source.toString()); - if (dir.dirName() == QLatin1String("qtbase")) + if (dir.dirName() == "qtbase") dir.cdUp(); if (filePath.isChildOf(dir)) @@ -1720,7 +1719,7 @@ bool BaseQtVersion::isQtQuickCompilerSupported(QString *reason) const } const QString qtQuickCompilerExecutable = - HostOsInfo::withExecutableSuffix(binPath().toString() + QLatin1String("/qtquickcompiler")); + HostOsInfo::withExecutableSuffix(binPath().toString() + "/qtquickcompiler"); if (!QFileInfo::exists(qtQuickCompilerExecutable)) { if (reason) *reason = QCoreApplication::translate("BaseQtVersion", "This Qt Version does not contain Qt Quick Compiler."); @@ -1748,22 +1747,22 @@ FileNameList BaseQtVersion::qtCorePaths() const foreach (const QFileInfo &info, infoList) { const QString file = info.fileName(); if (info.isDir() - && file.startsWith(QLatin1String("QtCore")) - && file.endsWith(QLatin1String(".framework"))) { + && file.startsWith("QtCore") + && file.endsWith(".framework")) { // handle Framework FileName lib(info); - dynamicLibs.append(lib.appendPath(file.left(file.lastIndexOf(QLatin1Char('.'))))); + dynamicLibs.append(lib.appendPath(file.left(file.lastIndexOf('.')))); } else if (info.isReadable()) { - if (file.startsWith(QLatin1String("libQtCore")) - || file.startsWith(QLatin1String("libQt5Core")) - || file.startsWith(QLatin1String("QtCore")) - || file.startsWith(QLatin1String("Qt5Core"))) { - if (file.endsWith(QLatin1String(".a")) || file.endsWith(QLatin1String(".lib"))) + if (file.startsWith("libQtCore") + || file.startsWith("libQt5Core") + || file.startsWith("QtCore") + || file.startsWith("Qt5Core")) { + if (file.endsWith(".a") || file.endsWith(".lib")) staticLibs.append(FileName(info)); - else if (file.endsWith(QLatin1String(".dll")) + else if (file.endsWith(".dll") || file.endsWith(QString::fromLatin1(".so.") + versionString) - || file.endsWith(QLatin1String(".so")) - || file.endsWith(QLatin1Char('.') + versionString + QLatin1String(".dylib"))) + || file.endsWith(".so") + || file.endsWith(QLatin1Char('.') + versionString + ".dylib")) dynamicLibs.append(FileName(info)); } } |