Commit 7862e312 authored by dt's avatar dt

Refactor OutputFormatter

Move link handling code to outputwindow from OutputFormatter

Move createOutputFormatter to the RunConfiguration

That makes it easier for Qt4RunConfiguration et all.
This also fixes that each time a runcontrol was rerun a new
OutputFormatter was created without deleting the old one, thus
increasing the memory usage.
parent 4e6c8e38
......@@ -37,8 +37,8 @@
using namespace ProjectExplorer;
using namespace TextEditor;
OutputFormatter::OutputFormatter(QObject *parent)
: QObject(parent)
OutputFormatter::OutputFormatter()
: QObject()
, m_formats(0)
{
initFormats();
......@@ -58,7 +58,6 @@ QPlainTextEdit *OutputFormatter::plainTextEdit() const
void OutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText)
{
m_plainTextEdit = plainText;
setParent(m_plainTextEdit);
}
void OutputFormatter::appendApplicationOutput(const QString &text, bool onStdErr)
......@@ -83,15 +82,6 @@ void OutputFormatter::append(const QString &text, const QTextCharFormat &format)
cursor.insertText(text, format);
}
void OutputFormatter::mousePressEvent(QMouseEvent * /*e*/)
{}
void OutputFormatter::mouseReleaseEvent(QMouseEvent * /*e*/)
{}
void OutputFormatter::mouseMoveEvent(QMouseEvent * /*e*/)
{}
void OutputFormatter::initFormats()
{
FontSettings fs = TextEditorSettings::instance()->fontSettings();
......@@ -117,3 +107,8 @@ void OutputFormatter::initFormats()
m_formats[StdErrFormat].setFont(font);
m_formats[StdErrFormat].setForeground(QColor(200, 0, 0));
}
void OutputFormatter::handleLink(const QString &href)
{
Q_UNUSED(href);
}
......@@ -46,7 +46,7 @@ class PROJECTEXPLORER_EXPORT OutputFormatter: public QObject
Q_OBJECT
public:
OutputFormatter(QObject *parent = 0);
OutputFormatter();
virtual ~OutputFormatter();
QPlainTextEdit *plainTextEdit() const;
......@@ -55,9 +55,7 @@ public:
virtual void appendApplicationOutput(const QString &text, bool onStdErr);
virtual void appendMessage(const QString &text, bool isError);
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
virtual void mouseMoveEvent(QMouseEvent *e);
virtual void handleLink(const QString &href);
protected:
enum Format {
......
......@@ -44,6 +44,8 @@
#include <coreplugin/icontext.h>
#include <find/basetextfind.h>
#include <aggregation/aggregate.h>
#include <texteditor/basetexteditor.h>
#include <projectexplorer/project.h>
#include <QtGui/QIcon>
#include <QtGui/QScrollBar>
......@@ -211,7 +213,7 @@ void OutputPane::createNewOutputWindow(RunControl *rc)
OutputWindow *ow = static_cast<OutputWindow *>(m_tabWidget->widget(i));
ow->grayOutOldContent();
ow->verticalScrollBar()->setValue(ow->verticalScrollBar()->maximum());
ow->setFormatter(rc->createOutputFormatter(ow));
ow->setFormatter(rc->outputFormatter());
m_outputWindows.insert(rc, ow);
found = true;
break;
......@@ -219,7 +221,7 @@ void OutputPane::createNewOutputWindow(RunControl *rc)
}
if (!found) {
OutputWindow *ow = new OutputWindow(m_tabWidget);
ow->setFormatter(rc->createOutputFormatter(ow));
ow->setFormatter(rc->outputFormatter());
Aggregation::Aggregate *agg = new Aggregation::Aggregate;
agg->add(ow);
agg->add(new Find::BaseTextFind(ow));
......@@ -376,6 +378,8 @@ OutputWindow::OutputWindow(QWidget *parent)
: QPlainTextEdit(parent)
, m_enforceNewline(false)
, m_scrollToBottom(false)
, m_linksActive(true)
, m_mousePressed(false)
{
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
//setCenterOnScroll(false);
......@@ -429,6 +433,42 @@ OutputWindow::~OutputWindow()
delete m_outputWindowContext;
}
void OutputWindow::mousePressEvent(QMouseEvent *e)
{
m_mousePressed = true;
QPlainTextEdit::mousePressEvent(e);
}
void OutputWindow::mouseReleaseEvent(QMouseEvent *e)
{
m_mousePressed = false;
if (!m_linksActive) {
// Mouse was released, activate links again
m_linksActive = true;
return;
}
const QString href = anchorAt(e->pos());
if (m_formatter)
m_formatter->handleLink(href);
QPlainTextEdit::mouseReleaseEvent(e);
}
void OutputWindow::mouseMoveEvent(QMouseEvent *e)
{
// Cursor was dragged to make a selection, deactivate links
if (m_mousePressed && textCursor().hasSelection())
m_linksActive = false;
if (!m_linksActive || anchorAt(e->pos()).isEmpty())
viewport()->setCursor(Qt::IBeamCursor);
else
viewport()->setCursor(Qt::PointingHandCursor);
QPlainTextEdit::mouseMoveEvent(e);
}
OutputFormatter *OutputWindow::formatter() const
{
return m_formatter;
......@@ -554,21 +594,3 @@ void OutputWindow::enableUndoRedo()
setMaximumBlockCount(0);
setUndoRedoEnabled(true);
}
void OutputWindow::mousePressEvent(QMouseEvent *e)
{
QPlainTextEdit::mousePressEvent(e);
m_formatter->mousePressEvent(e);
}
void OutputWindow::mouseReleaseEvent(QMouseEvent *e)
{
QPlainTextEdit::mouseReleaseEvent(e);
m_formatter->mouseReleaseEvent(e);
}
void OutputWindow::mouseMoveEvent(QMouseEvent *e)
{
QPlainTextEdit::mouseMoveEvent(e);
m_formatter->mouseMoveEvent(e);
}
......@@ -49,6 +49,7 @@ namespace Core {
namespace ProjectExplorer {
class OutputFormatter;
class RunControl;
class Project;
namespace Constants {
const char * const C_APP_OUTPUT = "Application Output";
......@@ -140,23 +141,24 @@ public:
void showEvent(QShowEvent *);
protected:
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
bool isScrollbarAtBottom() const;
void scrollToBottom();
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
virtual void mouseMoveEvent(QMouseEvent *e);
private:
void enableUndoRedo();
QString doNewlineEnfocement(const QString &out);
private:
Core::BaseContext *m_outputWindowContext;
OutputFormatter *m_formatter;
bool m_enforceNewline;
bool m_scrollToBottom;
bool m_linksActive;
bool m_mousePressed;
};
} // namespace Internal
......
......@@ -179,6 +179,11 @@ Target *RunConfiguration::target() const
return m_target;
}
ProjectExplorer::OutputFormatter *RunConfiguration::createOutputFormatter() const
{
return new OutputFormatter();
}
IRunConfigurationFactory::IRunConfigurationFactory(QObject *parent) :
QObject(parent)
{
......@@ -218,13 +223,23 @@ IRunControlFactory::~IRunControlFactory()
RunControl::RunControl(RunConfiguration *runConfiguration, QString mode)
: m_runMode(mode), m_runConfiguration(runConfiguration)
{
if (runConfiguration)
if (runConfiguration) {
m_displayName = runConfiguration->displayName();
m_outputFormatter = runConfiguration->createOutputFormatter();
}
// We need to ensure that there's always a OutputFormatter
if (!m_outputFormatter)
m_outputFormatter = new OutputFormatter();
}
RunControl::~RunControl()
{
delete m_outputFormatter;
}
OutputFormatter *RunControl::outputFormatter()
{
return m_outputFormatter;
}
QString RunControl::runMode() const
......@@ -242,11 +257,6 @@ bool RunControl::sameRunConfiguration(RunControl *other)
return other->m_runConfiguration.data() == m_runConfiguration.data();
}
OutputFormatter *RunControl::createOutputFormatter(QObject *parent)
{
return new OutputFormatter(parent);
}
void RunControl::bringApplicationToForeground(qint64 pid)
{
#ifdef Q_OS_MAC
......
......@@ -85,6 +85,8 @@ public:
Target *target() const;
virtual ProjectExplorer::OutputFormatter *createOutputFormatter() const;
signals:
void isEnabledChanged(bool value);
......@@ -169,7 +171,7 @@ public:
bool sameRunConfiguration(RunControl *other);
virtual OutputFormatter *createOutputFormatter(QObject *parent = 0);
OutputFormatter *outputFormatter();
QString runMode() const;
signals:
......@@ -189,6 +191,7 @@ private:
QString m_displayName;
QString m_runMode;
const QWeakPointer<RunConfiguration> m_runConfiguration;
OutputFormatter *m_outputFormatter;
#ifdef Q_OS_MAC
//these two are used to bring apps in the foreground on Mac
......
......@@ -22,8 +22,7 @@ HEADERS += qmlproject.h \
qmltaskmanager.h \
qmlprojectmanager_global.h \
qmlprojectmanagerconstants.h \
qmlprojecttarget.h \
qmloutputformatter.h
qmlprojecttarget.h
SOURCES += qmlproject.cpp \
qmlprojectplugin.cpp \
qmlprojectmanager.cpp \
......@@ -35,8 +34,7 @@ SOURCES += qmlproject.cpp \
qmlprojectrunconfigurationfactory.cpp \
qmlprojectapplicationwizard.cpp \
qmltaskmanager.cpp \
qmlprojecttarget.cpp \
qmloutputformatter.cpp
qmlprojecttarget.cpp
RESOURCES += qmlproject.qrc
OTHER_FILES += QmlProjectManager.pluginspec \
......
......@@ -27,9 +27,9 @@
**
**************************************************************************/
#include "qmlprojectrunconfiguration.h"
#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectrunconfiguration.h"
#include "qmlprojecttarget.h"
#include "projectexplorer/projectexplorer.h"
......
......@@ -27,7 +27,6 @@
**
**************************************************************************/
#include "qmloutputformatter.h"
#include "qmlprojectruncontrol.h"
#include "qmlprojectrunconfiguration.h"
#include "qmlprojectconstants.h"
......@@ -103,11 +102,6 @@ bool QmlRunControl::isRunning() const
return m_applicationLauncher.isRunning();
}
ProjectExplorer::OutputFormatter *QmlRunControl::createOutputFormatter(QObject *parent)
{
return new QmlOutputFormatter(parent);
}
void QmlRunControl::slotBringApplicationToForeground(qint64 pid)
{
bringApplicationToForeground(pid);
......
......@@ -51,8 +51,6 @@ public:
virtual void stop();
virtual bool isRunning() const;
virtual ProjectExplorer::OutputFormatter *createOutputFormatter(QObject *parent = 0);
private slots:
void processExited(int exitCode);
void slotBringApplicationToForeground(qint64 pid);
......
......@@ -35,6 +35,7 @@
#include "maemorunconfigurationwidget.h"
#include "maemotoolchain.h"
#include "qemuruntimemanager.h"
#include "qtoutputformatter.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
......@@ -113,6 +114,11 @@ QWidget *MaemoRunConfiguration::createConfigurationWidget()
return new MaemoRunConfigurationWidget(this);
}
ProjectExplorer::OutputFormatter *MaemoRunConfiguration::createConfigurationWidget() const
{
return new QtOutputFormatter(qt4Target()->qt4Project());
}
void MaemoRunConfiguration::proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro)
{
if (m_proFilePath == pro->path())
......
......@@ -68,6 +68,7 @@ public:
bool isEnabled(ProjectExplorer::BuildConfiguration *config) const;
QWidget *createConfigurationWidget();
ProjectExplorer::OutputFormatter *createConfigurationWidget() const;
Qt4Target *qt4Target() const;
Qt4BuildConfiguration *activeQt4BuildConfiguration() const;
......
......@@ -41,6 +41,7 @@
#include "qt4buildconfiguration.h"
#include "qt4projectmanagerconstants.h"
#include "s60createpackagestep.h"
#include "qtoutputformatter.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
......@@ -207,6 +208,11 @@ QWidget *S60DeviceRunConfiguration::createConfigurationWidget()
return new S60DeviceRunConfigurationWidget(this);
}
ProjectExplorer::OutputFormatter *S60DeviceRunConfiguration::createOutputFormatter() const
{
return new QtOutputFormatter(qt4Target()->qt4Project());
}
QVariantMap S60DeviceRunConfiguration::toMap() const
{
QVariantMap map(ProjectExplorer::RunConfiguration::toMap());
......
......@@ -74,6 +74,8 @@ public:
bool isEnabled(ProjectExplorer::BuildConfiguration *configuration) const;
QWidget *createConfigurationWidget();
ProjectExplorer::OutputFormatter *createOutputFormatter() const;
QString serialPortName() const;
void setSerialPortName(const QString &name);
......
......@@ -37,6 +37,7 @@
#include "s60devices.h"
#include "qt4buildconfiguration.h"
#include "qt4projectmanagerconstants.h"
#include "qtoutputformatter.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
......@@ -131,6 +132,11 @@ QWidget *S60EmulatorRunConfiguration::createConfigurationWidget()
return new S60EmulatorRunConfigurationWidget(this);
}
ProjectExplorer::OutputFormatter *S60EmulatorRunConfiguration::createOutputFormatter() const
{
return new QtOutputFormatter(qt4Target()->qt4Project());
}
QVariantMap S60EmulatorRunConfiguration::toMap() const
{
QVariantMap map(ProjectExplorer::RunConfiguration::toMap());
......
......@@ -67,6 +67,8 @@ public:
bool isEnabled(ProjectExplorer::BuildConfiguration *configuration) const;
QWidget *createConfigurationWidget();
ProjectExplorer::OutputFormatter *createOutputFormatter() const;
QString executable() const;
QVariantMap toMap() const;
......
......@@ -44,7 +44,8 @@ HEADERS += qt4projectmanagerplugin.h \
gettingstartedwelcomepage.h \
qt4buildconfiguration.h \
qt4target.h \
qmakeparser.h
qmakeparser.h \
qtoutputformatter.h
SOURCES += qt4projectmanagerplugin.cpp \
qt4projectmanager.cpp \
qt4project.cpp \
......@@ -85,7 +86,8 @@ SOURCES += qt4projectmanagerplugin.cpp \
gettingstartedwelcomepage.cpp \
qt4buildconfiguration.cpp \
qt4target.cpp \
qmakeparser.cpp
qmakeparser.cpp \
qtoutputformatter.cpp
FORMS += makestep.ui \
qmakestep.ui \
qt4projectconfigwidget.ui \
......
......@@ -36,6 +36,7 @@
#include "qt4target.h"
#include "qt4buildconfiguration.h"
#include "qt4projectmanagerconstants.h"
#include "qtoutputformatter.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
......@@ -669,6 +670,11 @@ ProjectExplorer::ToolChain::ToolChainType Qt4RunConfiguration::toolChainType() c
return qt4bc->toolChainType();
}
ProjectExplorer::OutputFormatter *Qt4RunConfiguration::createOutputFormatter() const
{
return new QtOutputFormatter(qt4Target()->qt4Project());
}
///
/// Qt4RunConfigurationFactory
/// This class is used to restore run settings (saved in .user files)
......
......@@ -93,6 +93,8 @@ public:
// TODO detectQtShadowBuild() ? how did this work ?
QVariantMap toMap() const;
ProjectExplorer::OutputFormatter *createOutputFormatter() const;
signals:
void commandLineArgumentsChanged(const QString&);
void workingDirectoryChanged(const QString&);
......
......@@ -27,24 +27,28 @@
**
**************************************************************************/
#include "qmloutputformatter.h"
#include "qtoutputformatter.h"
#include <texteditor/basetexteditor.h>
#include <qt4projectmanager/qt4project.h>
#include <QtCore/QFileInfo>
#include <QtGui/QPlainTextEdit>
using namespace ProjectExplorer;
using namespace QmlProjectManager::Internal;
using namespace Qt4ProjectManager;
QmlOutputFormatter::QmlOutputFormatter(QObject *parent)
: OutputFormatter(parent)
QtOutputFormatter::QtOutputFormatter(Qt4Project *project)
: OutputFormatter()
, m_qmlError(QLatin1String("(file:///[^:]+:\\d+:\\d+):"))
, m_linksActive(true)
, m_mousePressed(false)
, m_qtError(QLatin1String("Object::.*in (.*:\\d+)"))
, m_project(project)
{
}
void QmlOutputFormatter::appendApplicationOutput(const QString &text, bool onStdErr)
void QtOutputFormatter::appendApplicationOutput(const QString &text, bool onStdErr)
{
QTextCharFormat linkFormat;
linkFormat.setForeground(plainTextEdit()->palette().link().color());
......@@ -52,37 +56,33 @@ void QmlOutputFormatter::appendApplicationOutput(const QString &text, bool onStd
linkFormat.setAnchor(true);
// Create links from QML errors (anything of the form "file:///...:[line]:[column]:")
int index = 0;
while (m_qmlError.indexIn(text, index) != -1) {
if (m_qmlError.indexIn(text) != -1) {
const int matchPos = m_qmlError.pos(1);
const QString leader = text.mid(index, matchPos - index);
const QString leader = text.left(matchPos);
append(leader, onStdErr ? StdErrFormat : StdOutFormat);
const QString matched = m_qmlError.cap(1);
linkFormat.setAnchorHref(matched);
append(matched, linkFormat);
index = matchPos + m_qmlError.matchedLength() - 1;
}
append(text.mid(index), onStdErr ? StdErrFormat : StdOutFormat);
}
void QmlOutputFormatter::mousePressEvent(QMouseEvent * /*e*/)
{
m_mousePressed = true;
}
int index = matchPos + m_qmlError.matchedLength() - 1;
append(text.mid(index), onStdErr ? StdErrFormat : StdOutFormat);
} else if (m_qtError.indexIn(text) != -1) {
const int matchPos = m_qtError.pos(1);
const QString leader = text.left(matchPos);
append(leader, onStdErr ? StdErrFormat : StdOutFormat);
void QmlOutputFormatter::mouseReleaseEvent(QMouseEvent *e)
{
m_mousePressed = false;
const QString matched = m_qtError.cap(1);
linkFormat.setAnchorHref(m_qtError.cap(1));
append(matched, linkFormat);
if (!m_linksActive) {
// Mouse was released, activate links again
m_linksActive = true;
return;
int index = matchPos + m_qtError.matchedLength() - 1;
append(text.mid(index), onStdErr ? StdErrFormat : StdOutFormat);
}
}
const QString href = plainTextEdit()->anchorAt(e->pos());
void QtOutputFormatter::handleLink(const QString &href)
{
if (!href.isEmpty()) {
QRegExp qmlErrorLink(QLatin1String("^file://(/[^:]+):(\\d+):(\\d+)"));
......@@ -91,18 +91,30 @@ void QmlOutputFormatter::mouseReleaseEvent(QMouseEvent *e)
const int line = qmlErrorLink.cap(2).toInt();
const int column = qmlErrorLink.cap(3).toInt();
TextEditor::BaseTextEditor::openEditorAt(fileName, line, column - 1);
return;
}
}
}
void QmlOutputFormatter::mouseMoveEvent(QMouseEvent *e)
{
// Cursor was dragged to make a selection, deactivate links
if (m_mousePressed && plainTextEdit()->textCursor().hasSelection())
m_linksActive = false;
if (!m_linksActive || plainTextEdit()->anchorAt(e->pos()).isEmpty())
plainTextEdit()->viewport()->setCursor(Qt::IBeamCursor);
else
plainTextEdit()->viewport()->setCursor(Qt::PointingHandCursor);
QRegExp qtErrorLink(QLatin1String("^(.*):(\\d+)$"));
if (qtErrorLink.indexIn(href) != 1) {
QString fileName = qtErrorLink.cap(1);
const int line = qtErrorLink.cap(2).toInt();
QFileInfo fi(fileName);
if (fi.isRelative()) {
// Yeah fileName is relative, no suprise
Qt4Project *pro = m_project.data();
if (pro) {
QString baseName = fi.fileName();
foreach (const QString &file, pro->files(Project::AllFiles)) {
if (file.endsWith(baseName)) {
// pick the first one...
fileName = file;
break;
}
}
}
}
TextEditor::BaseTextEditor::openEditorAt(fileName, line, 0);
return;
}
}
}
......@@ -31,30 +31,29 @@
#define QMLOUTPUTFORMATTER_H
#include <projectexplorer/outputformatter.h>
#include <QtCore/QRegExp>
#include <QSharedPointer>
namespace QmlProjectManager {
namespace Internal {
namespace Qt4ProjectManager
{
class Qt4Project;
class QmlOutputFormatter: public ProjectExplorer::OutputFormatter
class QtOutputFormatter: public ProjectExplorer::OutputFormatter
{
public:
QmlOutputFormatter(QObject *parent = 0);
QtOutputFormatter(Qt4Project *project);
virtual void appendApplicationOutput(const QString &text, bool onStdErr);
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
virtual void mouseMoveEvent(QMouseEvent *e);
virtual void handleLink(const QString &href);
private:
QRegExp m_qmlError;
bool m_linksActive;
bool m_mousePressed;
QRegExp m_qtError;
QWeakPointer<Qt4Project> m_project;
};
} // namespace Internal
} // namespace QmlProjectManager
#endif // QMLOUTPUTFORMATTER_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment