2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2011-04-14 10:39:09 +02:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2011-04-14 10:39:09 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2011-04-14 10:39:09 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2011-04-14 10:39:09 +02:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2011-04-14 10:39:09 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
#include "outputwindow.h"
|
|
|
|
|
|
2011-04-21 13:42:17 +02:00
|
|
|
#include "actionmanager/actionmanager.h"
|
|
|
|
|
#include "coreconstants.h"
|
|
|
|
|
#include "icore.h"
|
2011-04-14 10:39:09 +02:00
|
|
|
|
2015-02-24 22:39:14 +02:00
|
|
|
#include <utils/outputformatter.h>
|
2013-08-02 12:15:04 +03:00
|
|
|
#include <utils/synchronousprocess.h>
|
|
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QAction>
|
|
|
|
|
#include <QScrollBar>
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
using namespace Utils;
|
|
|
|
|
|
2011-04-21 13:42:17 +02:00
|
|
|
namespace Core {
|
2011-04-14 10:39:09 +02:00
|
|
|
|
2015-02-24 22:39:14 +02:00
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
|
|
class OutputWindowPrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
2015-02-24 22:45:44 +02:00
|
|
|
OutputWindowPrivate(QTextDocument *document)
|
2015-02-24 22:39:14 +02:00
|
|
|
: outputWindowContext(0)
|
|
|
|
|
, formatter(0)
|
|
|
|
|
, enforceNewline(false)
|
|
|
|
|
, scrollToBottom(false)
|
|
|
|
|
, linksActive(true)
|
|
|
|
|
, mousePressed(false)
|
2015-08-17 16:29:09 +02:00
|
|
|
, m_zoomEnabled(false)
|
|
|
|
|
, m_originalFontSize(0)
|
2015-02-24 22:39:14 +02:00
|
|
|
, maxLineCount(100000)
|
2015-02-24 22:45:44 +02:00
|
|
|
, cursor(document)
|
2015-02-24 22:39:14 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~OutputWindowPrivate()
|
|
|
|
|
{
|
|
|
|
|
ICore::removeContextObject(outputWindowContext);
|
|
|
|
|
delete outputWindowContext;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IContext *outputWindowContext;
|
|
|
|
|
Utils::OutputFormatter *formatter;
|
|
|
|
|
|
|
|
|
|
bool enforceNewline;
|
|
|
|
|
bool scrollToBottom;
|
|
|
|
|
bool linksActive;
|
|
|
|
|
bool mousePressed;
|
2015-08-17 16:29:09 +02:00
|
|
|
bool m_zoomEnabled;
|
|
|
|
|
float m_originalFontSize;
|
2015-02-24 22:39:14 +02:00
|
|
|
int maxLineCount;
|
2015-02-24 22:45:44 +02:00
|
|
|
QTextCursor cursor;
|
2015-02-24 22:39:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
|
2011-04-14 10:39:09 +02:00
|
|
|
/*******************/
|
|
|
|
|
|
2014-11-16 10:52:41 +02:00
|
|
|
OutputWindow::OutputWindow(Context context, QWidget *parent)
|
2011-04-14 10:39:09 +02:00
|
|
|
: QPlainTextEdit(parent)
|
2015-02-24 22:45:44 +02:00
|
|
|
, d(new Internal::OutputWindowPrivate(document()))
|
2011-04-14 10:39:09 +02:00
|
|
|
{
|
|
|
|
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
|
|
|
|
//setCenterOnScroll(false);
|
|
|
|
|
setFrameShape(QFrame::NoFrame);
|
|
|
|
|
setMouseTracking(true);
|
2012-12-11 17:37:02 +01:00
|
|
|
setUndoRedoEnabled(false);
|
2011-04-14 10:39:09 +02:00
|
|
|
|
2015-02-24 22:39:14 +02:00
|
|
|
d->outputWindowContext = new IContext;
|
|
|
|
|
d->outputWindowContext->setContext(context);
|
|
|
|
|
d->outputWindowContext->setWidget(this);
|
|
|
|
|
ICore::addContextObject(d->outputWindowContext);
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
QAction *undoAction = new QAction(this);
|
|
|
|
|
QAction *redoAction = new QAction(this);
|
|
|
|
|
QAction *cutAction = new QAction(this);
|
|
|
|
|
QAction *copyAction = new QAction(this);
|
|
|
|
|
QAction *pasteAction = new QAction(this);
|
|
|
|
|
QAction *selectAllAction = new QAction(this);
|
|
|
|
|
|
2014-11-16 10:52:41 +02:00
|
|
|
ActionManager::registerAction(undoAction, Constants::UNDO, context);
|
|
|
|
|
ActionManager::registerAction(redoAction, Constants::REDO, context);
|
|
|
|
|
ActionManager::registerAction(cutAction, Constants::CUT, context);
|
|
|
|
|
ActionManager::registerAction(copyAction, Constants::COPY, context);
|
|
|
|
|
ActionManager::registerAction(pasteAction, Constants::PASTE, context);
|
|
|
|
|
ActionManager::registerAction(selectAllAction, Constants::SELECTALL, context);
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
connect(undoAction, SIGNAL(triggered()), this, SLOT(undo()));
|
|
|
|
|
connect(redoAction, SIGNAL(triggered()), this, SLOT(redo()));
|
|
|
|
|
connect(cutAction, SIGNAL(triggered()), this, SLOT(cut()));
|
|
|
|
|
connect(copyAction, SIGNAL(triggered()), this, SLOT(copy()));
|
|
|
|
|
connect(pasteAction, SIGNAL(triggered()), this, SLOT(paste()));
|
|
|
|
|
connect(selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll()));
|
|
|
|
|
|
|
|
|
|
connect(this, SIGNAL(undoAvailable(bool)), undoAction, SLOT(setEnabled(bool)));
|
|
|
|
|
connect(this, SIGNAL(redoAvailable(bool)), redoAction, SLOT(setEnabled(bool)));
|
|
|
|
|
connect(this, SIGNAL(copyAvailable(bool)), cutAction, SLOT(setEnabled(bool))); // OutputWindow never read-only
|
|
|
|
|
connect(this, SIGNAL(copyAvailable(bool)), copyAction, SLOT(setEnabled(bool)));
|
|
|
|
|
|
|
|
|
|
undoAction->setEnabled(false);
|
|
|
|
|
redoAction->setEnabled(false);
|
|
|
|
|
cutAction->setEnabled(false);
|
|
|
|
|
copyAction->setEnabled(false);
|
2015-04-28 17:24:52 +02:00
|
|
|
|
|
|
|
|
m_scrollTimer.setInterval(10);
|
|
|
|
|
m_scrollTimer.setSingleShot(true);
|
|
|
|
|
connect(&m_scrollTimer, &QTimer::timeout,
|
|
|
|
|
this, &OutputWindow::scrollToBottom);
|
|
|
|
|
m_lastMessage.start();
|
2015-08-17 16:29:09 +02:00
|
|
|
|
|
|
|
|
d->m_originalFontSize = font().pointSizeF();
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OutputWindow::~OutputWindow()
|
|
|
|
|
{
|
2015-02-24 22:39:14 +02:00
|
|
|
delete d;
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::mousePressEvent(QMouseEvent * e)
|
|
|
|
|
{
|
2015-02-24 22:39:14 +02:00
|
|
|
d->mousePressed = true;
|
2011-04-14 10:39:09 +02:00
|
|
|
QPlainTextEdit::mousePressEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::mouseReleaseEvent(QMouseEvent *e)
|
|
|
|
|
{
|
2015-02-24 22:39:14 +02:00
|
|
|
d->mousePressed = false;
|
2011-04-14 10:39:09 +02:00
|
|
|
|
2015-02-24 22:39:14 +02:00
|
|
|
if (d->linksActive) {
|
2011-04-14 10:39:09 +02:00
|
|
|
const QString href = anchorAt(e->pos());
|
2015-02-24 22:39:14 +02:00
|
|
|
if (d->formatter)
|
|
|
|
|
d->formatter->handleLink(href);
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mouse was released, activate links again
|
2015-02-24 22:39:14 +02:00
|
|
|
d->linksActive = true;
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
QPlainTextEdit::mouseReleaseEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::mouseMoveEvent(QMouseEvent *e)
|
|
|
|
|
{
|
|
|
|
|
// Cursor was dragged to make a selection, deactivate links
|
2015-02-24 22:39:14 +02:00
|
|
|
if (d->mousePressed && textCursor().hasSelection())
|
|
|
|
|
d->linksActive = false;
|
2011-04-14 10:39:09 +02:00
|
|
|
|
2015-02-24 22:39:14 +02:00
|
|
|
if (!d->linksActive || anchorAt(e->pos()).isEmpty())
|
2011-04-14 10:39:09 +02:00
|
|
|
viewport()->setCursor(Qt::IBeamCursor);
|
|
|
|
|
else
|
|
|
|
|
viewport()->setCursor(Qt::PointingHandCursor);
|
|
|
|
|
QPlainTextEdit::mouseMoveEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::resizeEvent(QResizeEvent *e)
|
|
|
|
|
{
|
|
|
|
|
//Keep scrollbar at bottom of window while resizing, to ensure we keep scrolling
|
|
|
|
|
//This can happen if window is resized while building, or if the horizontal scrollbar appears
|
|
|
|
|
bool atBottom = isScrollbarAtBottom();
|
|
|
|
|
QPlainTextEdit::resizeEvent(e);
|
|
|
|
|
if (atBottom)
|
|
|
|
|
scrollToBottom();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::keyPressEvent(QKeyEvent *ev)
|
|
|
|
|
{
|
|
|
|
|
QPlainTextEdit::keyPressEvent(ev);
|
|
|
|
|
|
|
|
|
|
//Ensure we scroll also on Ctrl+Home or Ctrl+End
|
|
|
|
|
if (ev->matches(QKeySequence::MoveToStartOfDocument))
|
|
|
|
|
verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMinimum);
|
|
|
|
|
else if (ev->matches(QKeySequence::MoveToEndOfDocument))
|
|
|
|
|
verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMaximum);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OutputFormatter *OutputWindow::formatter() const
|
|
|
|
|
{
|
2015-02-24 22:39:14 +02:00
|
|
|
return d->formatter;
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::setFormatter(OutputFormatter *formatter)
|
|
|
|
|
{
|
2015-02-24 22:39:14 +02:00
|
|
|
d->formatter = formatter;
|
|
|
|
|
d->formatter->setPlainTextEdit(this);
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::showEvent(QShowEvent *e)
|
|
|
|
|
{
|
|
|
|
|
QPlainTextEdit::showEvent(e);
|
2015-02-24 22:39:14 +02:00
|
|
|
if (d->scrollToBottom)
|
2011-04-14 10:39:09 +02:00
|
|
|
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
|
2015-02-24 22:39:14 +02:00
|
|
|
d->scrollToBottom = false;
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-17 16:29:09 +02:00
|
|
|
void OutputWindow::wheelEvent(QWheelEvent *e)
|
|
|
|
|
{
|
|
|
|
|
if (d->m_zoomEnabled) {
|
|
|
|
|
if (e->modifiers() & Qt::ControlModifier) {
|
|
|
|
|
float delta = e->angleDelta().y() / 120.f;
|
|
|
|
|
zoomInF(delta);
|
|
|
|
|
emit wheelZoom();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-08-31 21:58:07 +03:00
|
|
|
QAbstractScrollArea::wheelEvent(e);
|
|
|
|
|
updateMicroFocus();
|
2015-08-17 16:29:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::setBaseFont(const QFont &newFont)
|
|
|
|
|
{
|
|
|
|
|
float zoom = fontZoom();
|
|
|
|
|
d->m_originalFontSize = newFont.pointSizeF();
|
|
|
|
|
QFont tmp = newFont;
|
|
|
|
|
float newZoom = qMax(d->m_originalFontSize + zoom, 4.0f);
|
|
|
|
|
tmp.setPointSizeF(newZoom);
|
|
|
|
|
setFont(tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float OutputWindow::fontZoom() const
|
|
|
|
|
{
|
|
|
|
|
return font().pointSizeF() - d->m_originalFontSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::setFontZoom(float zoom)
|
|
|
|
|
{
|
|
|
|
|
QFont f = font();
|
|
|
|
|
if (f.pointSizeF() == d->m_originalFontSize + zoom)
|
|
|
|
|
return;
|
|
|
|
|
float newZoom = qMax(d->m_originalFontSize + zoom, 4.0f);
|
|
|
|
|
f.setPointSizeF(newZoom);
|
|
|
|
|
setFont(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::setWheelZoomEnabled(bool enabled)
|
|
|
|
|
{
|
|
|
|
|
d->m_zoomEnabled = enabled;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-02 20:11:42 +02:00
|
|
|
QString OutputWindow::doNewlineEnforcement(const QString &out)
|
2011-04-14 10:39:09 +02:00
|
|
|
{
|
2015-02-24 22:39:14 +02:00
|
|
|
d->scrollToBottom = true;
|
2011-04-14 10:39:09 +02:00
|
|
|
QString s = out;
|
2015-02-24 22:39:14 +02:00
|
|
|
if (d->enforceNewline) {
|
2011-04-14 10:39:09 +02:00
|
|
|
s.prepend(QLatin1Char('\n'));
|
2015-02-24 22:39:14 +02:00
|
|
|
d->enforceNewline = false;
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (s.endsWith(QLatin1Char('\n'))) {
|
2015-02-24 22:39:14 +02:00
|
|
|
d->enforceNewline = true; // make appendOutputInline put in a newline next time
|
2011-04-14 10:39:09 +02:00
|
|
|
s.chop(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-29 09:36:04 +02:00
|
|
|
void OutputWindow::setMaxLineCount(int count)
|
|
|
|
|
{
|
2015-02-24 22:39:14 +02:00
|
|
|
d->maxLineCount = count;
|
|
|
|
|
setMaximumBlockCount(d->maxLineCount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int OutputWindow::maxLineCount() const
|
|
|
|
|
{
|
|
|
|
|
return d->maxLineCount;
|
2011-04-29 09:36:04 +02:00
|
|
|
}
|
|
|
|
|
|
2011-04-14 10:39:09 +02:00
|
|
|
void OutputWindow::appendMessage(const QString &output, OutputFormat format)
|
|
|
|
|
{
|
2015-02-03 23:48:19 +02:00
|
|
|
const QString out = SynchronousProcess::normalizeNewlines(output);
|
2015-02-24 22:39:14 +02:00
|
|
|
setMaximumBlockCount(d->maxLineCount);
|
2015-04-28 17:24:52 +02:00
|
|
|
const bool atBottom = isScrollbarAtBottom() || m_scrollTimer.isActive();
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
if (format == ErrorMessageFormat || format == NormalMessageFormat) {
|
|
|
|
|
|
2015-02-24 22:39:14 +02:00
|
|
|
d->formatter->appendMessage(doNewlineEnforcement(out), format);
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
bool sameLine = format == StdOutFormatSameLine
|
|
|
|
|
|| format == StdErrFormatSameLine;
|
|
|
|
|
|
|
|
|
|
if (sameLine) {
|
2015-02-24 22:39:14 +02:00
|
|
|
d->scrollToBottom = true;
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
int newline = -1;
|
2015-02-24 22:39:14 +02:00
|
|
|
bool enforceNewline = d->enforceNewline;
|
|
|
|
|
d->enforceNewline = false;
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
if (!enforceNewline) {
|
|
|
|
|
newline = out.indexOf(QLatin1Char('\n'));
|
|
|
|
|
moveCursor(QTextCursor::End);
|
|
|
|
|
if (newline != -1)
|
2015-02-24 22:39:14 +02:00
|
|
|
d->formatter->appendMessage(out.left(newline), format);// doesn't enforce new paragraph like appendPlainText
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString s = out.mid(newline+1);
|
|
|
|
|
if (s.isEmpty()) {
|
2015-02-24 22:39:14 +02:00
|
|
|
d->enforceNewline = true;
|
2011-04-14 10:39:09 +02:00
|
|
|
} else {
|
|
|
|
|
if (s.endsWith(QLatin1Char('\n'))) {
|
2015-02-24 22:39:14 +02:00
|
|
|
d->enforceNewline = true;
|
2011-04-14 10:39:09 +02:00
|
|
|
s.chop(1);
|
|
|
|
|
}
|
2015-02-24 22:39:14 +02:00
|
|
|
d->formatter->appendMessage(QLatin1Char('\n') + s, format);
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
2015-02-24 22:39:14 +02:00
|
|
|
d->formatter->appendMessage(doNewlineEnforcement(out), format);
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-28 17:24:52 +02:00
|
|
|
if (atBottom) {
|
|
|
|
|
if (m_lastMessage.elapsed() < 5) {
|
|
|
|
|
m_scrollTimer.start();
|
|
|
|
|
} else {
|
|
|
|
|
m_scrollTimer.stop();
|
|
|
|
|
scrollToBottom();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_lastMessage.start();
|
2011-04-14 10:39:09 +02:00
|
|
|
enableUndoRedo();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO rename
|
2011-04-29 09:36:04 +02:00
|
|
|
void OutputWindow::appendText(const QString &textIn, const QTextCharFormat &format)
|
2011-04-14 10:39:09 +02:00
|
|
|
{
|
2015-02-03 23:48:19 +02:00
|
|
|
const QString text = SynchronousProcess::normalizeNewlines(textIn);
|
2015-02-24 22:39:14 +02:00
|
|
|
if (d->maxLineCount > 0 && document()->blockCount() >= d->maxLineCount)
|
2011-04-14 10:39:09 +02:00
|
|
|
return;
|
|
|
|
|
const bool atBottom = isScrollbarAtBottom();
|
2015-02-24 22:45:44 +02:00
|
|
|
if (!d->cursor.atEnd())
|
|
|
|
|
d->cursor.movePosition(QTextCursor::End);
|
|
|
|
|
d->cursor.beginEditBlock();
|
|
|
|
|
d->cursor.insertText(doNewlineEnforcement(text), format);
|
2011-04-14 10:39:09 +02:00
|
|
|
|
2015-02-24 22:39:14 +02:00
|
|
|
if (d->maxLineCount > 0 && document()->blockCount() >= d->maxLineCount) {
|
2011-04-14 10:39:09 +02:00
|
|
|
QTextCharFormat tmp;
|
|
|
|
|
tmp.setFontWeight(QFont::Bold);
|
2015-02-24 22:45:44 +02:00
|
|
|
d->cursor.insertText(doNewlineEnforcement(tr("Additional output omitted") + QLatin1Char('\n')), tmp);
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
2015-02-24 22:45:44 +02:00
|
|
|
d->cursor.endEditBlock();
|
2011-04-14 10:39:09 +02:00
|
|
|
if (atBottom)
|
|
|
|
|
scrollToBottom();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool OutputWindow::isScrollbarAtBottom() const
|
|
|
|
|
{
|
|
|
|
|
return verticalScrollBar()->value() == verticalScrollBar()->maximum();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::clear()
|
|
|
|
|
{
|
2015-02-24 22:39:14 +02:00
|
|
|
d->enforceNewline = false;
|
2011-04-14 10:39:09 +02:00
|
|
|
QPlainTextEdit::clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::scrollToBottom()
|
|
|
|
|
{
|
|
|
|
|
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
|
2011-04-21 13:42:17 +02:00
|
|
|
// QPlainTextEdit destroys the first calls value in case of multiline
|
|
|
|
|
// text, so make sure that the scroll bar actually gets the value set.
|
|
|
|
|
// Is a noop if the first call succeeded.
|
|
|
|
|
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::grayOutOldContent()
|
|
|
|
|
{
|
2015-02-24 22:45:44 +02:00
|
|
|
if (!d->cursor.atEnd())
|
|
|
|
|
d->cursor.movePosition(QTextCursor::End);
|
|
|
|
|
QTextCharFormat endFormat = d->cursor.charFormat();
|
2011-04-14 10:39:09 +02:00
|
|
|
|
2015-02-24 22:45:44 +02:00
|
|
|
d->cursor.select(QTextCursor::Document);
|
2011-04-14 10:39:09 +02:00
|
|
|
|
|
|
|
|
QTextCharFormat format;
|
|
|
|
|
const QColor bkgColor = palette().base().color();
|
|
|
|
|
const QColor fgdColor = palette().text().color();
|
|
|
|
|
double bkgFactor = 0.50;
|
|
|
|
|
double fgdFactor = 1.-bkgFactor;
|
|
|
|
|
format.setForeground(QColor((bkgFactor * bkgColor.red() + fgdFactor * fgdColor.red()),
|
|
|
|
|
(bkgFactor * bkgColor.green() + fgdFactor * fgdColor.green()),
|
|
|
|
|
(bkgFactor * bkgColor.blue() + fgdFactor * fgdColor.blue()) ));
|
2015-02-24 22:45:44 +02:00
|
|
|
d->cursor.mergeCharFormat(format);
|
2011-04-14 10:39:09 +02:00
|
|
|
|
2015-05-07 12:59:01 +02:00
|
|
|
d->cursor.movePosition(QTextCursor::End);
|
2015-02-24 22:45:44 +02:00
|
|
|
d->cursor.setCharFormat(endFormat);
|
|
|
|
|
d->cursor.insertBlock(QTextBlockFormat());
|
2011-04-14 10:39:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::enableUndoRedo()
|
|
|
|
|
{
|
|
|
|
|
setMaximumBlockCount(0);
|
|
|
|
|
setUndoRedoEnabled(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OutputWindow::setWordWrapEnabled(bool wrap)
|
|
|
|
|
{
|
|
|
|
|
if (wrap)
|
|
|
|
|
setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
|
|
|
|
else
|
|
|
|
|
setWordWrapMode(QTextOption::NoWrap);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-21 13:42:17 +02:00
|
|
|
} // namespace Core
|