aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/texteditor
diff options
context:
space:
mode:
authormae <qt-info@nokia.com>2010-07-02 13:47:14 +0200
committermae <qt-info@nokia.com>2010-07-02 13:48:57 +0200
commit6ef602d121bbd32055471cb6ce51c2bf5736ff89 (patch)
treeece46d0dc38785685d46d905d505233301a6c989 /src/plugins/texteditor
parent038d943f9aa3b0fcc6099ba9bc692b9a7fc97a3f (diff)
add basic support to show refactor markers
See BaseTextEditor::setRefactorMarkers(...). The markers support a clicked signal via BaseTextEditor and tooltips. They feature a cursor, but are always positioned at the end of the line (not block!). As special gimmick they do extend the document width when they are positioned outside the document area.
Diffstat (limited to 'src/plugins/texteditor')
-rw-r--r--src/plugins/texteditor/basetextdocumentlayout.cpp18
-rw-r--r--src/plugins/texteditor/basetextdocumentlayout.h5
-rw-r--r--src/plugins/texteditor/basetexteditor.cpp71
-rw-r--r--src/plugins/texteditor/basetexteditor.h13
-rw-r--r--src/plugins/texteditor/basetexteditor_p.h3
-rw-r--r--src/plugins/texteditor/images/refactormarker.pngbin0 -> 4886 bytes
-rw-r--r--src/plugins/texteditor/refactoroverlay.cpp76
-rw-r--r--src/plugins/texteditor/refactoroverlay.h51
-rw-r--r--src/plugins/texteditor/texteditor.pro6
-rw-r--r--src/plugins/texteditor/texteditor.qrc3
10 files changed, 230 insertions, 16 deletions
diff --git a/src/plugins/texteditor/basetextdocumentlayout.cpp b/src/plugins/texteditor/basetextdocumentlayout.cpp
index 648c0a610e5..58427566bb0 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.cpp
+++ b/src/plugins/texteditor/basetextdocumentlayout.cpp
@@ -512,4 +512,22 @@ void BaseTextDocumentLayout::doFoldOrUnfold(const QTextBlock& block, bool unfold
setFolded(block, !unfold);
}
+void BaseTextDocumentLayout::setRequiredWidth(int width)
+{
+ int oldw = m_requiredWidth;
+ m_requiredWidth = width;
+ int dw = QPlainTextDocumentLayout::documentSize().width();
+ if (oldw > dw || width > dw)
+ emitDocumentSizeChanged();
+}
+
+
+QSizeF BaseTextDocumentLayout::documentSize() const
+{
+ QSizeF size = QPlainTextDocumentLayout::documentSize();
+ size.setWidth(qMax((qreal)m_requiredWidth, size.width()));
+ return size;
+}
+
+
diff --git a/src/plugins/texteditor/basetextdocumentlayout.h b/src/plugins/texteditor/basetextdocumentlayout.h
index c76a6283399..b3b20ce2d4e 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.h
+++ b/src/plugins/texteditor/basetextdocumentlayout.h
@@ -159,6 +159,11 @@ public:
void emitDocumentSizeChanged() { emit documentSizeChanged(documentSize()); }
int lastSaveRevision;
bool hasMarks;
+
+ int m_requiredWidth;
+ void setRequiredWidth(int width);
+
+ QSizeF documentSize() const;
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp
index a543d85d484..12d2c113214 100644
--- a/src/plugins/texteditor/basetexteditor.cpp
+++ b/src/plugins/texteditor/basetexteditor.cpp
@@ -81,6 +81,8 @@
#include <QtGui/QInputDialog>
#include <QtGui/QMenu>
+//#define DO_FOO
+
using namespace TextEditor;
using namespace TextEditor::Internal;
@@ -189,6 +191,7 @@ BaseTextEditor::BaseTextEditor(QWidget *parent)
d->m_overlay = new TextEditorOverlay(this);
d->m_snippetOverlay = new TextEditorOverlay(this);
d->m_searchResultOverlay = new TextEditorOverlay(this);
+ d->m_refactorOverlay = new RefactorOverlay(this);
d->setupDocumentSignals(d->m_document);
d->setupDocumentSignals(d->m_document);
@@ -217,6 +220,10 @@ BaseTextEditor::BaseTextEditor(QWidget *parent)
// (void) new QShortcut(tr("F9"), this, SLOT(slotToggleMark()), 0, Qt::WidgetShortcut);
// (void) new QShortcut(tr("F11"), this, SLOT(slotToggleBlockVisible()));
+#ifdef DO_FOO
+ (void) new QShortcut(tr("CTRL+D"), this, SLOT(doFoo()));
+#endif
+
// parentheses matcher
d->m_formatRange = true;
@@ -1610,12 +1617,10 @@ void BaseTextEditor::documentAboutToBeReloaded()
QPlainTextEdit::setExtraSelections(QList<QTextEdit::ExtraSelection>());
// clear all overlays
- if (d->m_overlay)
- d->m_overlay->clear();
- if (d->m_snippetOverlay)
- d->m_snippetOverlay->clear();
- if (d->m_searchResultOverlay)
- d->m_searchResultOverlay->clear();
+ d->m_overlay->clear();
+ d->m_snippetOverlay->clear();
+ d->m_searchResultOverlay->clear();
+ d->m_refactorOverlay->clear();
}
void BaseTextEditor::documentReloaded()
@@ -1867,6 +1872,7 @@ BaseTextEditorPrivate::BaseTextEditorPrivate()
m_overlay(0),
m_snippetOverlay(0),
m_searchResultOverlay(0),
+ m_refactorOverlay(0),
visibleFoldedBlockNumber(-1),
suggestedVisibleFoldedBlockNumber(-1),
m_mouseOnFoldedMarker(false),
@@ -2001,6 +2007,12 @@ bool BaseTextEditor::viewportEvent(QEvent *event)
return true; // eat tooltip event when control is pressed
const QPoint &pos = he->pos();
+ RefactorMarker refactorMarker = d->m_refactorOverlay->markerAt(pos);
+ if (refactorMarker.isValid() && !refactorMarker.tooltip.isEmpty()) {
+ QToolTip::showText(he->globalPos(), refactorMarker.tooltip, viewport(), refactorMarker.rect);
+ return true;
+ }
+
// Allow plugins to show tooltips
const QTextCursor &c = cursorForPosition(pos);
QPoint cursorPos = mapToGlobal(cursorRect(c).bottomRight() + QPoint(1,1));
@@ -2763,10 +2775,10 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
d->m_animator->draw(&painter, cursorRect(cursor).topLeft());
}
- if (d->m_overlay && d->m_overlay->isVisible())
+ if (d->m_overlay->isVisible())
d->m_overlay->paint(&painter, e->rect());
- if (d->m_snippetOverlay && d->m_snippetOverlay->isVisible())
+ if (d->m_snippetOverlay->isVisible())
d->m_snippetOverlay->paint(&painter, e->rect());
if (!d->m_searchResultOverlay->isEmpty()) {
@@ -2774,6 +2786,9 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
d->m_searchResultOverlay->clear();
}
+ if (!d->m_refactorOverlay->isEmpty())
+ d->m_refactorOverlay->paint(&painter, e->rect());
+
// draw the cursor last, on top of everything
if (cursor_layout) {
painter.setPen(cursor_pen);
@@ -3373,11 +3388,13 @@ void BaseTextEditor::mouseMoveEvent(QMouseEvent *e)
d->foldedBlockTimer.start(40, this);
}
+ const RefactorMarker refactorMarker = d->m_refactorOverlay->markerAt(e->pos());
+
// Update the mouse cursor
- if (collapsedBlock.isValid() && !d->m_mouseOnFoldedMarker) {
+ if ((collapsedBlock.isValid() || refactorMarker.isValid()) && !d->m_mouseOnFoldedMarker) {
d->m_mouseOnFoldedMarker = true;
viewport()->setCursor(Qt::PointingHandCursor);
- } else if (!collapsedBlock.isValid() && d->m_mouseOnFoldedMarker) {
+ } else if (!collapsedBlock.isValid() && !refactorMarker.isValid() && d->m_mouseOnFoldedMarker) {
d->m_mouseOnFoldedMarker = false;
viewport()->setCursor(Qt::IBeamCursor);
}
@@ -3420,10 +3437,16 @@ void BaseTextEditor::mousePressEvent(QMouseEvent *e)
viewport()->setCursor(Qt::IBeamCursor);
}
- updateLink(e);
+ RefactorMarker refactorMarker = d->m_refactorOverlay->markerAt(e->pos());
+ if (refactorMarker.isValid()) {
+ qDebug() << "refactorMarkerClicked" << refactorMarker.cursor.position();
+ emit refactorMarkerClicked(refactorMarker);
+ } else {
+ updateLink(e);
- if (d->m_currentLink.isValid())
- d->m_linkPressed = true;
+ if (d->m_currentLink.isValid())
+ d->m_linkPressed = true;
+ }
}
#ifdef Q_OS_LINUX
@@ -5388,3 +5411,25 @@ QString BaseTextEditorEditable::contextHelpId() const
e->textCursor().position());
return m_contextHelpId;
}
+
+
+void BaseTextEditor::setRefactorMarkers(const Internal::RefactorMarkers &markers)
+{
+ foreach (const Internal::RefactorMarker &marker, d->m_refactorOverlay->markers())
+ requestBlockUpdate(marker.cursor.block());
+ d->m_refactorOverlay->setMarkers(markers);
+ foreach (const Internal::RefactorMarker &marker, markers)
+ requestBlockUpdate(marker.cursor.block());
+}
+
+void BaseTextEditor::doFoo() {
+#ifdef DO_FOO
+ qDebug() << Q_FUNC_INFO;
+ RefactorMarkers markers = d->m_refactorOverlay->markers();
+ RefactorMarker marker;
+ marker.tooltip = "Hello World";
+ marker.cursor = textCursor();
+ markers += marker;
+ setRefactorMarkers(markers);
+#endif
+}
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index 1bab6597a77..2f96437f94c 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -51,6 +51,10 @@ namespace TextEditor {
namespace Internal {
class BaseTextEditorPrivate;
class TextEditorOverlay;
+ class RefactorOverlay;
+ class RefactorMarker;
+ typedef QList<RefactorMarker> RefactorMarkers;
+
}
class ITextMarkable;
@@ -315,6 +319,7 @@ private:
Internal::BaseTextEditorPrivate *d;
friend class Internal::BaseTextEditorPrivate;
friend class Internal::TextEditorOverlay;
+ friend class Internal::RefactorOverlay;
public:
QWidget *extraArea() const;
@@ -348,6 +353,13 @@ public:
QList<QTextEdit::ExtraSelection> extraSelections(ExtraSelectionKind kind) const;
QString extraSelectionTooltip(int pos) const;
+
+ void setRefactorMarkers(const Internal::RefactorMarkers &markers);
+signals:
+ void refactorMarkerClicked(const Internal::RefactorMarker &marker);
+
+public:
+
struct BlockRange
{
BlockRange() : first(0), last(-1) {}
@@ -516,6 +528,7 @@ private slots:
void _q_highlightBlocks();
void slotSelectionChanged();
void _q_animateUpdate(int position, QPointF lastPos, QRectF rect);
+ void doFoo();
};
diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h
index 9cb7788186f..6419976777e 100644
--- a/src/plugins/texteditor/basetexteditor_p.h
+++ b/src/plugins/texteditor/basetexteditor_p.h
@@ -35,6 +35,7 @@
#include "displaysettings.h"
#include "texteditoroverlay.h"
#include "fontsettings.h"
+#include "refactoroverlay.h"
#include <utils/changeset.h>
@@ -199,6 +200,8 @@ public:
QTextCharFormat m_occurrencesFormat;
QTextCharFormat m_occurrenceRenameFormat;
+ RefactorOverlay *m_refactorOverlay;
+
QBasicTimer foldedBlockTimer;
int visibleFoldedBlockNumber;
int suggestedVisibleFoldedBlockNumber;
diff --git a/src/plugins/texteditor/images/refactormarker.png b/src/plugins/texteditor/images/refactormarker.png
new file mode 100644
index 00000000000..dd7d7a2417c
--- /dev/null
+++ b/src/plugins/texteditor/images/refactormarker.png
Binary files differ
diff --git a/src/plugins/texteditor/refactoroverlay.cpp b/src/plugins/texteditor/refactoroverlay.cpp
new file mode 100644
index 00000000000..006de650236
--- /dev/null
+++ b/src/plugins/texteditor/refactoroverlay.cpp
@@ -0,0 +1,76 @@
+#include "refactoroverlay.h"
+#include <QPainter>
+#include <QTextBlock>
+#include "basetextdocumentlayout.h"
+#include <QDebug>
+
+using namespace TextEditor::Internal;
+
+RefactorOverlay::RefactorOverlay(BaseTextEditor *editor) :
+ QObject(editor),
+ m_editor(editor),
+ m_maxWidth(0),
+ m_icon(":/texteditor/images/refactormarker.png")
+{
+}
+
+void RefactorOverlay::paint(QPainter *painter, const QRect &clip)
+{
+ QTextBlock lastBlock;
+ int position = 0;
+ m_maxWidth = 0;
+ for (int i = 0; i < m_markers.size(); ++i) {
+
+ // position counts how many refactor markers are in a single block
+ if (m_markers.at(i).cursor.block() != lastBlock) {
+ lastBlock = m_markers.at(i).cursor.block();
+ position = 0;
+ } else {
+ position++;
+ }
+
+ paintMarker(m_markers.at(i), position, painter, clip);
+ }
+
+ if (BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(m_editor->document()->documentLayout())) {
+ documentLayout->setRequiredWidth(m_maxWidth);
+ }
+
+}
+
+RefactorMarker RefactorOverlay::markerAt(const QPoint &pos) const
+{
+ QPointF offset = m_editor->contentOffset();
+ foreach(const RefactorMarker &marker, m_markers) {
+ if (marker.rect.translated(offset.toPoint()).contains(pos))
+ return marker;
+ }
+ return RefactorMarker();
+}
+
+void RefactorOverlay::paintMarker(const RefactorMarker& marker, int position,
+ QPainter *painter, const QRect &clip)
+{
+ QPointF offset = m_editor->contentOffset();
+ QRectF geometry = m_editor->blockBoundingGeometry(marker.cursor.block()).translated(offset);
+
+ if (geometry.top() > clip.bottom() + 10 || geometry.bottom() < clip.top() - 10)
+ return; // marker not visible
+
+ QTextCursor cursor = marker.cursor;
+ cursor.movePosition(QTextCursor::EndOfLine);
+ QRect r = m_editor->cursorRect(cursor);
+
+ QIcon icon = marker.icon;
+ if (icon.isNull())
+ icon = m_icon;
+
+ QSize sz = icon.actualSize(QSize(INT_MAX, r.height()));
+
+ int x = r.right() + position * sz.width();
+ marker.rect = QRect(x, r.bottom() - sz.height(), sz.width(), sz.height()).translated(-offset.toPoint());
+ icon.paint(painter, marker.rect);
+ m_maxWidth = qMax((qreal)m_maxWidth, x + sz.width() - offset.x());
+}
+
+
diff --git a/src/plugins/texteditor/refactoroverlay.h b/src/plugins/texteditor/refactoroverlay.h
new file mode 100644
index 00000000000..ad44b843c73
--- /dev/null
+++ b/src/plugins/texteditor/refactoroverlay.h
@@ -0,0 +1,51 @@
+#ifndef REFACTOROVERLAY_H
+#define REFACTOROVERLAY_H
+
+#include "basetexteditor.h"
+#include <QTextCursor>
+#include <QObject>
+#include <QIcon>
+
+namespace TextEditor {
+namespace Internal {
+
+struct TEXTEDITOR_EXPORT RefactorMarker {
+ inline bool isValid() const { return !cursor.isNull(); }
+ QTextCursor cursor;
+ QString tooltip;
+ QIcon icon;
+ mutable QRect rect; // used to cache last drawing positin in document coordinates
+ QVariant data;
+};
+
+typedef QList<RefactorMarker> RefactorMarkers;
+
+class TEXTEDITOR_EXPORT RefactorOverlay : public QObject
+{
+ Q_OBJECT
+public:
+ explicit RefactorOverlay(BaseTextEditor *editor);
+
+ bool isEmpty() const { return m_markers.isEmpty(); }
+ void paint(QPainter *painter, const QRect &clip);
+
+ void setMarkers(const RefactorMarkers &markers) { m_markers = markers; }
+ RefactorMarkers markers() const { return m_markers; }
+
+ void clear() { m_markers.clear(); }
+
+ RefactorMarker markerAt(const QPoint &pos) const;
+
+private:
+ void paintMarker(const RefactorMarker& marker, int position, QPainter *painter, const QRect &clip);
+ RefactorMarkers m_markers;
+ BaseTextEditor *m_editor;
+ int m_maxWidth;
+ QIcon m_icon;
+
+};
+
+}
+}
+
+#endif // REFACTOROVERLAY_H
diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro
index d9eb3928053..65bc255c935 100644
--- a/src/plugins/texteditor/texteditor.pro
+++ b/src/plugins/texteditor/texteditor.pro
@@ -59,7 +59,8 @@ SOURCES += texteditorplugin.cpp \
generichighlighter/managedefinitionsdialog.cpp \
generichighlighter/highlightdefinitionmetadata.cpp \
generichighlighter/definitiondownloader.cpp \
- refactoringchanges.cpp
+ refactoringchanges.cpp \
+ refactoroverlay.cpp
HEADERS += texteditorplugin.h \
textfilewizard.h \
@@ -121,7 +122,8 @@ HEADERS += texteditorplugin.h \
generichighlighter/managedefinitionsdialog.h \
generichighlighter/highlightdefinitionmetadata.h \
generichighlighter/definitiondownloader.h \
- refactoringchanges.h
+ refactoringchanges.h \
+ refactoroverlay.h
FORMS += behaviorsettingspage.ui \
displaysettingspage.ui \
diff --git a/src/plugins/texteditor/texteditor.qrc b/src/plugins/texteditor/texteditor.qrc
index 191343ce0e6..0d131c4f3b1 100644
--- a/src/plugins/texteditor/texteditor.qrc
+++ b/src/plugins/texteditor/texteditor.qrc
@@ -1,7 +1,8 @@
<RCC>
- <qresource prefix="/texteditor" >
+ <qresource prefix="/texteditor">
<file>images/finddocuments.png</file>
<file>images/finddirectory.png</file>
<file>TextEditor.mimetypes.xml</file>
+ <file>images/refactormarker.png</file>
</qresource>
</RCC>