cpphoverhandler.cpp 6.47 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11
** 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
12 13 14
** 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.
15
**
16 17 18 19 20 21 22
** 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.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
hjk's avatar
hjk committed
25

con's avatar
con committed
26
#include "cpphoverhandler.h"
27

28
#include "cppeditorconstants.h"
29
#include "cppelementevaluator.h"
con's avatar
con committed
30

31
#include <coreplugin/helpmanager.h>
32 33 34 35
#include <cpptools/baseeditordocumentprocessor.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/editordocumenthandle.h>
#include <texteditor/convenience.h>
36
#include <texteditor/texteditor.h>
37 38

#include <utils/qtcassert.h>
con's avatar
con committed
39

40 41
#include <QTextCursor>
#include <QUrl>
con's avatar
con committed
42

43
using namespace Core;
44
using namespace TextEditor;
con's avatar
con committed
45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
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 (Convenience::convertPosition(editorWidget->document(), pos, &line, &column))
            return processor->hasDiagnosticsAt(line, column);
    }

    return false;
}

void processWithEditorDocumentProcessor(TextEditorWidget *editorWidget,
                                        const QPoint &point,
                                        int position)
{
    if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
        int line, column;
        if (Convenience::convertPosition(editorWidget->document(), position, &line, &column))
            processor->showDiagnosticTooltip(point, editorWidget, line, column);
    }
}

} // anonymous namespace

84 85 86
namespace CppEditor {
namespace Internal {

87
void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos)
con's avatar
con committed
88
{
89 90 91 92 93 94
    m_positionForEditorDocumentProcessor = -1;

    if (editorDocumentProcessorHasDiagnosticAt(editorWidget, pos)) {
        setIsDiagnosticTooltip(true);
        m_positionForEditorDocumentProcessor = pos;
    } else if (!editorWidget->extraSelectionTooltip(pos).isEmpty()) {
95
        setToolTip(editorWidget->extraSelectionTooltip(pos));
96
    } else {
97
        QTextCursor tc(editorWidget->document());
98 99
        tc.setPosition(pos);

100
        CppElementEvaluator evaluator(editorWidget);
101
        evaluator.setTextCursor(tc);
102 103 104 105 106 107 108 109
        evaluator.execute();
        if (evaluator.hasDiagnosis()) {
            setToolTip(evaluator.diagnosis());
            setIsDiagnosticTooltip(true);
        }
        if (evaluator.identifiedCppElement()) {
            const QSharedPointer<CppElement> &cppElement = evaluator.cppElement();
            if (!isDiagnosticTooltip())
110
                setToolTip(cppElement->tooltip);
111 112 113 114 115 116
            QStringList candidates = cppElement->helpIdCandidates;
            candidates.removeDuplicates();
            foreach (const QString &helpId, candidates) {
                if (helpId.isEmpty())
                    continue;

117
                const QMap<QString, QUrl> helpLinks = HelpManager::linksForIdentifier(helpId);
118
                if (!helpLinks.isEmpty()) {
119 120 121 122
                    setLastHelpItemIdentified(HelpItem(helpId,
                                                       cppElement->helpMark,
                                                       cppElement->helpCategory,
                                                       helpLinks));
123 124
                    break;
                }
125
            }
126 127
        }
    }
128
}
129

130
void CppHoverHandler::decorateToolTip()
131
{
132 133 134
    if (m_positionForEditorDocumentProcessor != -1)
        return;

135
    if (Qt::mightBeRichText(toolTip()))
136
        setToolTip(toolTip().toHtmlEscaped());
137

138 139 140
    if (isDiagnosticTooltip())
        return;

141
    const HelpItem &help = lastHelpItemIdentified();
142
    if (help.isValid()) {
143 144
        // 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.
145
        const HelpItem::Category category = help.category();
146
        const QString &contents = help.extractContent(false);
147
        if (!contents.isEmpty()) {
148
            if (category == HelpItem::ClassOrNamespace)
149 150
                setToolTip(help.helpId() + contents);
            else
Leandro Melo's avatar
Leandro Melo committed
151
                setToolTip(contents);
152 153 154
        } else if (category == HelpItem::Typedef ||
                   category == HelpItem::Enum ||
                   category == HelpItem::ClassOrNamespace) {
155 156 157
            // 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;
158
            if (category == HelpItem::Typedef)
159
                prefix = QLatin1String("typedef ");
160
            else if (category == HelpItem::Enum)
161 162
                prefix = QLatin1String("enum ");
            setToolTip(prefix + help.helpId());
163 164 165
        }
    }
}
166

167 168 169 170 171 172 173 174 175
void CppHoverHandler::operateTooltip(TextEditor::TextEditorWidget *editorWidget,
                                     const QPoint &point)
{
    if (m_positionForEditorDocumentProcessor != -1)
        processWithEditorDocumentProcessor(editorWidget, point, m_positionForEditorDocumentProcessor);
    else
        BaseHoverHandler::operateTooltip(editorWidget, point);
}

176 177
} // namespace Internal
} // namespace CppEditor