aboutsummaryrefslogtreecommitdiffstats
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
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.
-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 648c0a610e..58427566bb 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 c76a628339..b3b20ce2d4 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 a543d85d48..12d2c11321 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 1bab6597a7..2f96437f94 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 9cb7788186..6419976777 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 0000000000..dd7d7a2417
--- /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 0000000000..006de65023
--- /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 0000000000..ad44b843c7
--- /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 d9eb392805..65bc255c93 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 191343ce0e..0d131c4f3b 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>