compileoutputwindow.cpp 8.25 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
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 12 13 14
** 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 Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30 31
#include "compileoutputwindow.h"
#include "buildmanager.h"
Tobias Hunger's avatar
Tobias Hunger committed
32 33
#include "showoutputtaskhandler.h"
#include "task.h"
34 35
#include "projectexplorer.h"
#include "projectexplorersettings.h"
36
#include "taskhub.h"
con's avatar
con committed
37

38
#include <coreplugin/outputwindow.h>
39
#include <coreplugin/find/basetextfind.h>
Tobias Hunger's avatar
Tobias Hunger committed
40
#include <extensionsystem/pluginmanager.h>
41 42
#include <texteditor/texteditorsettings.h>
#include <texteditor/fontsettings.h>
43
#include <utils/ansiescapecodehandler.h>
con's avatar
con committed
44

45 46 47 48 49
#include <QIcon>
#include <QTextCharFormat>
#include <QTextBlock>
#include <QTextCursor>
#include <QPlainTextEdit>
50
#include <QToolButton>
con's avatar
con committed
51 52 53 54

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

Tobias Hunger's avatar
Tobias Hunger committed
55
namespace {
56
const int MAX_LINECOUNT = 100000;
Tobias Hunger's avatar
Tobias Hunger committed
57 58
}

59 60 61 62 63
namespace ProjectExplorer {
namespace Internal {

class CompileOutputTextEdit : public Core::OutputWindow
{
64
    Q_OBJECT
65 66 67
public:
    CompileOutputTextEdit(const Core::Context &context) : Core::OutputWindow(context)
    {
68 69 70
        fontSettingsChanged();
        connect(TextEditor::TextEditorSettings::instance(), SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
                this, SLOT(fontSettingsChanged()));
71 72 73 74 75 76 77 78 79 80 81
    }

    void addTask(const Task &task, int blocknumber)
    {
        m_taskids.insert(blocknumber, task.taskId);
    }

    void clearTasks()
    {
        m_taskids.clear();
    }
82 83 84
private slots:
    void fontSettingsChanged()
    {
85
        setFont(TextEditor::TextEditorSettings::fontSettings().font());
86
    }
87 88

protected:
Daniel Teske's avatar
Daniel Teske committed
89 90
    void mouseDoubleClickEvent(QMouseEvent *ev)
    {
91
        int line = cursorForPosition(ev->pos()).block().blockNumber();
Orgad Shaneh's avatar
Orgad Shaneh committed
92
        if (unsigned taskid = m_taskids.value(line, 0))
93
            TaskHub::showTaskInEditor(taskid);
Orgad Shaneh's avatar
Orgad Shaneh committed
94
        else
95 96 97 98 99 100 101 102 103 104
            QPlainTextEdit::mouseDoubleClickEvent(ev);
    }

private:
    QHash<int, unsigned int> m_taskids;   //Map blocknumber to taskId
};

} // namespace Internal
} // namespace ProjectExplorer

105
CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
106 107
    m_cancelBuildButton(new QToolButton),
    m_escapeCodeHandler(new Utils::AnsiEscapeCodeHandler)
con's avatar
con committed
108
{
109
    Core::Context context(Constants::C_COMPILE_OUTPUT);
110
    m_outputWindow = new CompileOutputTextEdit(context);
111
    m_outputWindow->setWindowTitle(tr("Compile Output"));
112
    m_outputWindow->setWindowIcon(QIcon(QLatin1String(Constants::ICON_WINDOW)));
113
    m_outputWindow->setReadOnly(true);
114
    m_outputWindow->setUndoRedoEnabled(false);
115
    m_outputWindow->setMaxLineCount(MAX_LINECOUNT);
116

117 118 119 120 121 122 123 124 125
    // Let selected text be colored as if the text edit was editable,
    // otherwise the highlight for searching is too light
    QPalette p = m_outputWindow->palette();
    QColor activeHighlight = p.color(QPalette::Active, QPalette::Highlight);
    p.setColor(QPalette::Highlight, activeHighlight);
    QColor activeHighlightedText = p.color(QPalette::Active, QPalette::HighlightedText);
    p.setColor(QPalette::HighlightedText, activeHighlightedText);
    m_outputWindow->setPalette(p);

126 127
    m_cancelBuildButton->setDefaultAction(cancelBuildAction);

con's avatar
con committed
128
    Aggregation::Aggregate *agg = new Aggregation::Aggregate;
129
    agg->add(m_outputWindow);
130
    agg->add(new Core::BaseTextFind(m_outputWindow));
131 132

    qRegisterMetaType<QTextCharFormat>("QTextCharFormat");
Tobias Hunger's avatar
Tobias Hunger committed
133 134

    m_handler = new ShowOutputTaskHandler(this);
135
    ExtensionSystem::PluginManager::addObject(m_handler);
136 137 138
    connect(ProjectExplorerPlugin::instance(), SIGNAL(settingsChanged()),
            this, SLOT(updateWordWrapMode()));
    updateWordWrapMode();
Tobias Hunger's avatar
Tobias Hunger committed
139 140 141 142
}

CompileOutputWindow::~CompileOutputWindow()
{
143
    ExtensionSystem::PluginManager::removeObject(m_handler);
Tobias Hunger's avatar
Tobias Hunger committed
144
    delete m_handler;
145
    delete m_cancelBuildButton;
146
    delete m_escapeCodeHandler;
con's avatar
con committed
147 148
}

149 150
void CompileOutputWindow::updateWordWrapMode()
{
151
    m_outputWindow->setWordWrapEnabled(ProjectExplorerPlugin::projectExplorerSettings().wrapAppOutput);
152 153
}

154
bool CompileOutputWindow::hasFocus() const
con's avatar
con committed
155
{
156
    return m_outputWindow->hasFocus();
con's avatar
con committed
157 158
}

159
bool CompileOutputWindow::canFocus() const
con's avatar
con committed
160 161 162 163 164 165
{
    return true;
}

void CompileOutputWindow::setFocus()
{
166
    m_outputWindow->setFocus();
con's avatar
con committed
167 168 169 170
}

QWidget *CompileOutputWindow::outputWidget(QWidget *)
{
171
    return m_outputWindow;
con's avatar
con committed
172 173
}

174 175 176 177 178
QList<QWidget *> CompileOutputWindow::toolBarWidgets() const
{
     return QList<QWidget *>() << m_cancelBuildButton;
}

179
static QColor mix_colors(const QColor &a, const QColor &b)
con's avatar
con committed
180
{
181 182
    return QColor((a.red() + 2 * b.red()) / 3, (a.green() + 2 * b.green()) / 3,
                  (a.blue() + 2* b.blue()) / 3, (a.alpha() + 2 * b.alpha()) / 3);
183 184
}

185
void CompileOutputWindow::appendText(const QString &text, BuildStep::OutputFormat format)
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
{
    QPalette p = m_outputWindow->palette();
    QTextCharFormat textFormat;
    switch (format) {
    case BuildStep::NormalOutput:
        textFormat.setForeground(p.color(QPalette::Text));
        textFormat.setFontWeight(QFont::Normal);
        break;
    case BuildStep::ErrorOutput:
        textFormat.setForeground(mix_colors(p.color(QPalette::Text), QColor(Qt::red)));
        textFormat.setFontWeight(QFont::Normal);
        break;
    case BuildStep::MessageOutput:
        textFormat.setForeground(mix_colors(p.color(QPalette::Text), QColor(Qt::blue)));
        break;
    case BuildStep::ErrorMessageOutput:
        textFormat.setForeground(mix_colors(p.color(QPalette::Text), QColor(Qt::red)));
        textFormat.setFontWeight(QFont::Bold);
        break;

    }

208 209 210
    foreach (const Utils::FormattedText &output,
             m_escapeCodeHandler->parseText(Utils::FormattedText(text, textFormat)))
        m_outputWindow->appendText(output.text, output.format);
con's avatar
con committed
211 212 213 214
}

void CompileOutputWindow::clearContents()
{
215
    m_outputWindow->clear();
216
    m_outputWindow->clearTasks();
Tobias Hunger's avatar
Tobias Hunger committed
217
    m_taskPositions.clear();
con's avatar
con committed
218 219
}

220
void CompileOutputWindow::visibilityChanged(bool)
con's avatar
con committed
221
{
222

con's avatar
con committed
223 224 225 226 227 228
}

int CompileOutputWindow::priorityInStatusBar() const
{
    return 50;
}
229

230
bool CompileOutputWindow::canNext() const
231 232 233 234
{
    return false;
}

235
bool CompileOutputWindow::canPrevious() const
236 237 238 239 240 241 242 243 244 245 246 247 248 249
{
    return false;
}

void CompileOutputWindow::goToNext()
{

}

void CompileOutputWindow::goToPrev()
{

}

250
bool CompileOutputWindow::canNavigate() const
251 252 253
{
    return false;
}
Tobias Hunger's avatar
Tobias Hunger committed
254 255 256

void CompileOutputWindow::registerPositionOf(const Task &task)
{
257
    int blocknumber = m_outputWindow->blockCount();
Tobias Hunger's avatar
Tobias Hunger committed
258 259
    if (blocknumber > MAX_LINECOUNT)
        return;
260

261
    m_taskPositions.insert(task.taskId, blocknumber);
262
    m_outputWindow->addTask(task, blocknumber);
Tobias Hunger's avatar
Tobias Hunger committed
263 264 265 266 267 268 269 270 271 272
}

bool CompileOutputWindow::knowsPositionOf(const Task &task)
{
    return (m_taskPositions.contains(task.taskId));
}

void CompileOutputWindow::showPositionOf(const Task &task)
{
    int position = m_taskPositions.value(task.taskId);
273
    QTextCursor newCursor(m_outputWindow->document()->findBlockByNumber(position));
Tobias Hunger's avatar
Tobias Hunger committed
274
    newCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
275
    m_outputWindow->setTextCursor(newCursor);
Tobias Hunger's avatar
Tobias Hunger committed
276
}
277

278 279 280 281 282 283
void CompileOutputWindow::flush()
{
    if (m_escapeCodeHandler)
        m_escapeCodeHandler->endFormatScope();
}

284
#include "compileoutputwindow.moc"