diff options
Diffstat (limited to 'src/plugins/cpptools/cpphoverhandler.cpp')
-rw-r--r-- | src/plugins/cpptools/cpphoverhandler.cpp | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/plugins/cpptools/cpphoverhandler.cpp b/src/plugins/cpptools/cpphoverhandler.cpp new file mode 100644 index 0000000000..d01102f4f2 --- /dev/null +++ b/src/plugins/cpptools/cpphoverhandler.cpp @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** 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 <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 CppTools { + +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 CppTools |