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.
This commit is contained in:
dt
2010-07-13 15:02:37 +02:00
parent 4e6c8e38be
commit 7862e31256
21 changed files with 177 additions and 113 deletions

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 \

View File

@@ -27,9 +27,9 @@
**
**************************************************************************/
#include "qmlprojectrunconfiguration.h"
#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectrunconfiguration.h"
#include "qmlprojecttarget.h"
#include "projectexplorer/projectexplorer.h"

View File

@@ -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);

View File

@@ -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);

View File

@@ -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())

View File

@@ -68,6 +68,7 @@ public:
bool isEnabled(ProjectExplorer::BuildConfiguration *config) const;
QWidget *createConfigurationWidget();
ProjectExplorer::OutputFormatter *createConfigurationWidget() const;
Qt4Target *qt4Target() const;
Qt4BuildConfiguration *activeQt4BuildConfiguration() const;

View File

@@ -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());

View File

@@ -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);

View File

@@ -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());

View File

@@ -67,6 +67,8 @@ public:
bool isEnabled(ProjectExplorer::BuildConfiguration *configuration) const;
QWidget *createConfigurationWidget();
ProjectExplorer::OutputFormatter *createOutputFormatter() const;
QString executable() const;
QVariantMap toMap() const;

View File

@@ -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 \

View File

@@ -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)

View File

@@ -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&);

View File

@@ -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;
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);
const QString matched = m_qtError.cap(1);
linkFormat.setAnchorHref(m_qtError.cap(1));
append(matched, linkFormat);
int index = matchPos + m_qtError.matchedLength() - 1;
append(text.mid(index), onStdErr ? StdErrFormat : StdOutFormat);
}
append(text.mid(index), onStdErr ? StdErrFormat : StdOutFormat);
}
void QmlOutputFormatter::mousePressEvent(QMouseEvent * /*e*/)
void QtOutputFormatter::handleLink(const QString &href)
{
m_mousePressed = true;
}
void QmlOutputFormatter::mouseReleaseEvent(QMouseEvent *e)
{
m_mousePressed = false;
if (!m_linksActive) {
// Mouse was released, activate links again
m_linksActive = true;
return;
}
const QString href = plainTextEdit()->anchorAt(e->pos());
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;
}
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;
}
}
}
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);
}

View File

@@ -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