forked from qt-creator/qt-creator
CppEditor: Extract CppLocalRenaming
Now CppEditorWidget is much less convoluted with the local rename mode. This class can be reused since there is no dependency on CPPEditorWidget. Change-Id: If513e59a03214cf9f2e3831f7e3616c001e1f036 Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
#include "cppeditorplugin.h"
|
#include "cppeditorplugin.h"
|
||||||
#include "cppfollowsymbolundercursor.h"
|
#include "cppfollowsymbolundercursor.h"
|
||||||
#include "cpphighlighter.h"
|
#include "cpphighlighter.h"
|
||||||
|
#include "cpplocalrenaming.h"
|
||||||
#include "cpppreprocessordialog.h"
|
#include "cpppreprocessordialog.h"
|
||||||
#include "cppquickfixassistant.h"
|
#include "cppquickfixassistant.h"
|
||||||
|
|
||||||
@@ -437,12 +438,7 @@ public:
|
|||||||
QTimer *m_updateFunctionDeclDefLinkTimer;
|
QTimer *m_updateFunctionDeclDefLinkTimer;
|
||||||
QHash<int, QTextCharFormat> m_semanticHighlightFormatMap;
|
QHash<int, QTextCharFormat> m_semanticHighlightFormatMap;
|
||||||
|
|
||||||
QList<QTextEdit::ExtraSelection> m_renameSelections;
|
CppLocalRenaming m_localRenaming;
|
||||||
int m_currentRenameSelection;
|
|
||||||
static const int NoCurrentRenameSelection = -1;
|
|
||||||
bool m_inRename, m_inRenameChanged, m_firstRenameChange;
|
|
||||||
QTextCursor m_currentRenameSelectionBegin;
|
|
||||||
QTextCursor m_currentRenameSelectionEnd;
|
|
||||||
|
|
||||||
CppTools::SemanticInfo m_lastSemanticInfo;
|
CppTools::SemanticInfo m_lastSemanticInfo;
|
||||||
QList<TextEditor::QuickFixOperation::Ptr> m_quickFixes;
|
QList<TextEditor::QuickFixOperation::Ptr> m_quickFixes;
|
||||||
@@ -467,10 +463,7 @@ CPPEditorWidgetPrivate::CPPEditorWidgetPrivate(CPPEditorWidget *q)
|
|||||||
: q(q)
|
: q(q)
|
||||||
, m_modelManager(CppModelManagerInterface::instance())
|
, m_modelManager(CppModelManagerInterface::instance())
|
||||||
, m_cppEditorDocument(qobject_cast<CPPEditorDocument *>(q->baseTextDocument()))
|
, m_cppEditorDocument(qobject_cast<CPPEditorDocument *>(q->baseTextDocument()))
|
||||||
, m_currentRenameSelection(NoCurrentRenameSelection)
|
, m_localRenaming(q)
|
||||||
, m_inRename(false)
|
|
||||||
, m_inRenameChanged(false)
|
|
||||||
, m_firstRenameChange(false)
|
|
||||||
, m_highlightRevision(0)
|
, m_highlightRevision(0)
|
||||||
, m_referencesRevision(0)
|
, m_referencesRevision(0)
|
||||||
, m_referencesCursorPosition(0)
|
, m_referencesCursorPosition(0)
|
||||||
@@ -536,7 +529,11 @@ void CPPEditorWidget::ctor()
|
|||||||
|
|
||||||
connect(baseTextDocument(), SIGNAL(filePathChanged(QString,QString)),
|
connect(baseTextDocument(), SIGNAL(filePathChanged(QString,QString)),
|
||||||
this, SLOT(onFilePathChanged()));
|
this, SLOT(onFilePathChanged()));
|
||||||
onFilePathChanged();
|
|
||||||
|
connect(&d->m_localRenaming, SIGNAL(finished()),
|
||||||
|
this, SLOT(onLocalRenamingFinished()));
|
||||||
|
connect(&d->m_localRenaming, SIGNAL(processKeyPressNormally(QKeyEvent*)),
|
||||||
|
this, SLOT(onLocalRenamingProcessKeyPressNormally(QKeyEvent*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPEditorWidget::~CPPEditorWidget()
|
CPPEditorWidget::~CPPEditorWidget()
|
||||||
@@ -627,99 +624,28 @@ void CPPEditorWidget::createToolBar(CPPEditor *editor)
|
|||||||
|
|
||||||
void CPPEditorWidget::paste()
|
void CPPEditorWidget::paste()
|
||||||
{
|
{
|
||||||
if (d->m_currentRenameSelection == d->NoCurrentRenameSelection) {
|
if (d->m_localRenaming.handlePaste())
|
||||||
BaseTextEditorWidget::paste();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
startRename();
|
|
||||||
BaseTextEditorWidget::paste();
|
BaseTextEditorWidget::paste();
|
||||||
finishRename();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPPEditorWidget::cut()
|
void CPPEditorWidget::cut()
|
||||||
{
|
{
|
||||||
if (d->m_currentRenameSelection == d->NoCurrentRenameSelection) {
|
if (d->m_localRenaming.handlePaste())
|
||||||
BaseTextEditorWidget::cut();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
startRename();
|
|
||||||
BaseTextEditorWidget::cut();
|
BaseTextEditorWidget::cut();
|
||||||
finishRename();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPPEditorWidget::selectAll()
|
void CPPEditorWidget::selectAll()
|
||||||
{
|
{
|
||||||
// if we are currently renaming a symbol
|
if (d->m_localRenaming.handleSelectAll())
|
||||||
// and the cursor is over that symbol, select just that symbol
|
|
||||||
if (d->m_currentRenameSelection != d->NoCurrentRenameSelection) {
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
int selectionBegin = d->m_currentRenameSelectionBegin.position();
|
|
||||||
int selectionEnd = d->m_currentRenameSelectionEnd.position();
|
|
||||||
|
|
||||||
if (cursor.position() >= selectionBegin
|
|
||||||
&& cursor.position() <= selectionEnd) {
|
|
||||||
cursor.setPosition(selectionBegin);
|
|
||||||
cursor.setPosition(selectionEnd, QTextCursor::KeepAnchor);
|
|
||||||
setTextCursor(cursor);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseTextEditorWidget::selectAll();
|
BaseTextEditorWidget::selectAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPPEditorWidget::startRename()
|
|
||||||
{
|
|
||||||
d->m_inRenameChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPPEditorWidget::finishRename()
|
|
||||||
{
|
|
||||||
if (!d->m_inRenameChanged)
|
|
||||||
return;
|
|
||||||
|
|
||||||
d->m_inRename = true;
|
|
||||||
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
cursor.joinPreviousEditBlock();
|
|
||||||
|
|
||||||
cursor.setPosition(d->m_currentRenameSelectionEnd.position());
|
|
||||||
cursor.setPosition(d->m_currentRenameSelectionBegin.position(), QTextCursor::KeepAnchor);
|
|
||||||
d->m_renameSelections[d->m_currentRenameSelection].cursor = cursor;
|
|
||||||
QString text = cursor.selectedText();
|
|
||||||
|
|
||||||
for (int i = 0; i < d->m_renameSelections.size(); ++i) {
|
|
||||||
if (i == d->m_currentRenameSelection)
|
|
||||||
continue;
|
|
||||||
QTextEdit::ExtraSelection &s = d->m_renameSelections[i];
|
|
||||||
int pos = s.cursor.selectionStart();
|
|
||||||
s.cursor.removeSelectedText();
|
|
||||||
s.cursor.insertText(text);
|
|
||||||
s.cursor.setPosition(pos, QTextCursor::KeepAnchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
setExtraSelections(CodeSemanticsSelection, d->m_renameSelections);
|
|
||||||
cursor.endEditBlock();
|
|
||||||
|
|
||||||
d->m_inRename = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPPEditorWidget::abortRename()
|
|
||||||
{
|
|
||||||
if (d->m_currentRenameSelection <= d->NoCurrentRenameSelection)
|
|
||||||
return;
|
|
||||||
d->m_renameSelections[d->m_currentRenameSelection].format
|
|
||||||
= baseTextDocument()->fontSettings().toTextCharFormat(TextEditor::C_OCCURRENCES);
|
|
||||||
d->m_currentRenameSelection = d->NoCurrentRenameSelection;
|
|
||||||
d->m_currentRenameSelectionBegin = QTextCursor();
|
|
||||||
d->m_currentRenameSelectionEnd = QTextCursor();
|
|
||||||
setExtraSelections(CodeSemanticsSelection, d->m_renameSelections);
|
|
||||||
|
|
||||||
semanticRehighlight(/* force = */ true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Called by \c CppEditorSupport when the document corresponding to the
|
/// \brief Called by \c CppEditorSupport when the document corresponding to the
|
||||||
/// file in this editor is updated.
|
/// file in this editor is updated.
|
||||||
void CPPEditorWidget::onDocumentUpdated()
|
void CPPEditorWidget::onDocumentUpdated()
|
||||||
@@ -811,8 +737,7 @@ void CPPEditorWidget::markSymbolsNow()
|
|||||||
cursor.setPosition(cursor.position() + len, QTextCursor::KeepAnchor);
|
cursor.setPosition(cursor.position() + len, QTextCursor::KeepAnchor);
|
||||||
|
|
||||||
QTextEdit::ExtraSelection sel;
|
QTextEdit::ExtraSelection sel;
|
||||||
sel.format = baseTextDocument()->fontSettings()
|
sel.format = textCharFormat(TextEditor::C_OCCURRENCES);
|
||||||
.toTextCharFormat(TextEditor::C_OCCURRENCES);
|
|
||||||
sel.cursor = cursor;
|
sel.cursor = cursor;
|
||||||
selections.append(sel);
|
selections.append(sel);
|
||||||
}
|
}
|
||||||
@@ -838,12 +763,11 @@ static QList<int> lazyFindReferences(Scope *scope, QString code, Document::Ptr d
|
|||||||
|
|
||||||
void CPPEditorWidget::markSymbols(const QTextCursor &tc, const SemanticInfo &info)
|
void CPPEditorWidget::markSymbols(const QTextCursor &tc, const SemanticInfo &info)
|
||||||
{
|
{
|
||||||
abortRename();
|
d->m_localRenaming.stop();
|
||||||
|
|
||||||
if (!info.doc)
|
if (!info.doc)
|
||||||
return;
|
return;
|
||||||
const QTextCharFormat &occurrencesFormat
|
const QTextCharFormat &occurrencesFormat = textCharFormat(TextEditor::C_OCCURRENCES);
|
||||||
= baseTextDocument()->fontSettings().toTextCharFormat(TextEditor::C_OCCURRENCES);
|
|
||||||
if (const Macro *macro = findCanonicalMacro(textCursor(), info.doc)) {
|
if (const Macro *macro = findCanonicalMacro(textCursor(), info.doc)) {
|
||||||
QList<QTextEdit::ExtraSelection> selections;
|
QList<QTextEdit::ExtraSelection> selections;
|
||||||
|
|
||||||
@@ -907,52 +831,17 @@ void CPPEditorWidget::renameSymbolUnderCursor()
|
|||||||
if (!d->m_modelManager)
|
if (!d->m_modelManager)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CppEditorSupport *edSup = d->m_modelManager->cppEditorSupport(editor());
|
CppEditorSupport *ces = d->m_modelManager->cppEditorSupport(editor());
|
||||||
updateSemanticInfo(edSup->recalculateSemanticInfo());
|
updateSemanticInfo(ces->recalculateSemanticInfo());
|
||||||
abortRename();
|
|
||||||
|
|
||||||
QTextCursor c = textCursor();
|
if (!d->m_localRenaming.start()) // Rename local symbol
|
||||||
|
renameUsages(); // Rename non-local symbol or macro
|
||||||
for (int i = 0; i < d->m_renameSelections.size(); ++i) {
|
|
||||||
QTextEdit::ExtraSelection s = d->m_renameSelections.at(i);
|
|
||||||
if (c.position() >= s.cursor.anchor()
|
|
||||||
&& c.position() <= s.cursor.position()) {
|
|
||||||
d->m_currentRenameSelection = i;
|
|
||||||
d->m_firstRenameChange = true;
|
|
||||||
d->m_currentRenameSelectionBegin = QTextCursor(c.document()->docHandle(),
|
|
||||||
d->m_renameSelections[i].cursor.selectionStart());
|
|
||||||
d->m_currentRenameSelectionEnd = QTextCursor(c.document()->docHandle(),
|
|
||||||
d->m_renameSelections[i].cursor.selectionEnd());
|
|
||||||
d->m_renameSelections[i].format
|
|
||||||
= baseTextDocument()->fontSettings().toTextCharFormat(TextEditor::C_OCCURRENCES_RENAME);;
|
|
||||||
setExtraSelections(CodeSemanticsSelection, d->m_renameSelections);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->m_renameSelections.isEmpty())
|
|
||||||
renameUsages();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPPEditorWidget::onContentsChanged(int position, int charsRemoved, int charsAdded)
|
void CPPEditorWidget::onContentsChanged(int position, int charsRemoved, int charsAdded)
|
||||||
{
|
{
|
||||||
if (d->m_currentRenameSelection == d->NoCurrentRenameSelection || d->m_inRename)
|
Q_UNUSED(position)
|
||||||
return;
|
Q_UNUSED(charsAdded)
|
||||||
|
|
||||||
if (position + charsAdded == d->m_currentRenameSelectionBegin.position()) {
|
|
||||||
// we are inserting at the beginning of the rename selection => expand
|
|
||||||
d->m_currentRenameSelectionBegin.setPosition(position);
|
|
||||||
d->m_renameSelections[d->m_currentRenameSelection].cursor.setPosition(position,
|
|
||||||
QTextCursor::KeepAnchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the condition looks odd, but keep in mind that the begin
|
|
||||||
// and end cursors do move automatically
|
|
||||||
d->m_inRenameChanged = (position >= d->m_currentRenameSelectionBegin.position()
|
|
||||||
&& position + charsAdded <= d->m_currentRenameSelectionEnd.position());
|
|
||||||
|
|
||||||
if (!d->m_inRenameChanged)
|
|
||||||
abortRename();
|
|
||||||
|
|
||||||
if (charsRemoved > 0)
|
if (charsRemoved > 0)
|
||||||
updateUses();
|
updateUses();
|
||||||
@@ -1025,13 +914,11 @@ void CPPEditorWidget::updateOutlineIndex()
|
|||||||
d->m_updateOutlineIndexTimer->start();
|
d->m_updateOutlineIndexTimer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPPEditorWidget::highlightUses(const QList<SemanticInfo::Use> &uses,
|
QList<QTextEdit::ExtraSelection> CPPEditorWidget::createSelectionsFromUses(
|
||||||
QList<QTextEdit::ExtraSelection> *selections)
|
const QList<SemanticInfo::Use> &uses)
|
||||||
{
|
{
|
||||||
bool isUnused = false;
|
QList<QTextEdit::ExtraSelection> result;
|
||||||
|
const bool isUnused = uses.size() == 1;
|
||||||
if (uses.size() == 1)
|
|
||||||
isUnused = true;
|
|
||||||
|
|
||||||
foreach (const SemanticInfo::Use &use, uses) {
|
foreach (const SemanticInfo::Use &use, uses) {
|
||||||
if (use.isInvalid())
|
if (use.isInvalid())
|
||||||
@@ -1039,19 +926,21 @@ void CPPEditorWidget::highlightUses(const QList<SemanticInfo::Use> &uses,
|
|||||||
|
|
||||||
QTextEdit::ExtraSelection sel;
|
QTextEdit::ExtraSelection sel;
|
||||||
if (isUnused)
|
if (isUnused)
|
||||||
sel.format = baseTextDocument()->fontSettings().toTextCharFormat(TextEditor::C_OCCURRENCES_UNUSED);
|
sel.format = textCharFormat(TextEditor::C_OCCURRENCES_UNUSED);
|
||||||
else
|
else
|
||||||
sel.format = baseTextDocument()->fontSettings().toTextCharFormat(TextEditor::C_OCCURRENCES);
|
sel.format = textCharFormat(TextEditor::C_OCCURRENCES);
|
||||||
|
|
||||||
const int anchor = document()->findBlockByNumber(use.line - 1).position() + use.column - 1;
|
const int position = document()->findBlockByNumber(use.line - 1).position() + use.column - 1;
|
||||||
const int position = anchor + use.length;
|
const int anchor = position + use.length;
|
||||||
|
|
||||||
sel.cursor = QTextCursor(document());
|
sel.cursor = QTextCursor(document());
|
||||||
sel.cursor.setPosition(anchor);
|
sel.cursor.setPosition(anchor);
|
||||||
sel.cursor.setPosition(position, QTextCursor::KeepAnchor);
|
sel.cursor.setPosition(position, QTextCursor::KeepAnchor);
|
||||||
|
|
||||||
selections->append(sel);
|
result.append(sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPPEditorWidget::updateOutlineIndexNow()
|
void CPPEditorWidget::updateOutlineIndexNow()
|
||||||
@@ -1094,7 +983,7 @@ void CPPEditorWidget::updateUses()
|
|||||||
|
|
||||||
void CPPEditorWidget::updateUsesNow()
|
void CPPEditorWidget::updateUsesNow()
|
||||||
{
|
{
|
||||||
if (d->m_currentRenameSelection != d->NoCurrentRenameSelection)
|
if (d->m_localRenaming.isActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
semanticRehighlight();
|
semanticRehighlight();
|
||||||
@@ -1258,8 +1147,7 @@ bool CPPEditorWidget::event(QEvent *e)
|
|||||||
switch (e->type()) {
|
switch (e->type()) {
|
||||||
case QEvent::ShortcutOverride:
|
case QEvent::ShortcutOverride:
|
||||||
// handle escape manually if a rename is active
|
// handle escape manually if a rename is active
|
||||||
if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape
|
if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape && d->m_localRenaming.isActive()) {
|
||||||
&& d->m_currentRenameSelection != d->NoCurrentRenameSelection) {
|
|
||||||
e->accept();
|
e->accept();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1335,88 +1223,11 @@ void CPPEditorWidget::contextMenuEvent(QContextMenuEvent *e)
|
|||||||
|
|
||||||
void CPPEditorWidget::keyPressEvent(QKeyEvent *e)
|
void CPPEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||||
{
|
{
|
||||||
if (d->m_currentRenameSelection == d->NoCurrentRenameSelection) {
|
if (d->m_localRenaming.handleKeyPressEvent(e))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!handleDocumentationComment(e))
|
if (!handleDocumentationComment(e))
|
||||||
TextEditor::BaseTextEditorWidget::keyPressEvent(e);
|
TextEditor::BaseTextEditorWidget::keyPressEvent(e);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// key handling for renames
|
|
||||||
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
const QTextCursor::MoveMode moveMode = (e->modifiers() & Qt::ShiftModifier)
|
|
||||||
? QTextCursor::KeepAnchor
|
|
||||||
: QTextCursor::MoveAnchor;
|
|
||||||
|
|
||||||
switch (e->key()) {
|
|
||||||
case Qt::Key_Enter:
|
|
||||||
case Qt::Key_Return:
|
|
||||||
case Qt::Key_Escape:
|
|
||||||
abortRename();
|
|
||||||
e->accept();
|
|
||||||
return;
|
|
||||||
case Qt::Key_Home: {
|
|
||||||
// Send home to start of name when within the name and not at the start
|
|
||||||
if (cursor.position() > d->m_currentRenameSelectionBegin.position()
|
|
||||||
&& cursor.position() <= d->m_currentRenameSelectionEnd.position()) {
|
|
||||||
cursor.setPosition(d->m_currentRenameSelectionBegin.position(), moveMode);
|
|
||||||
setTextCursor(cursor);
|
|
||||||
e->accept();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Qt::Key_End: {
|
|
||||||
// Send end to end of name when within the name and not at the end
|
|
||||||
if (cursor.position() >= d->m_currentRenameSelectionBegin.position()
|
|
||||||
&& cursor.position() < d->m_currentRenameSelectionEnd.position()) {
|
|
||||||
cursor.setPosition(d->m_currentRenameSelectionEnd.position(), moveMode);
|
|
||||||
setTextCursor(cursor);
|
|
||||||
e->accept();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Qt::Key_Backspace: {
|
|
||||||
if (cursor.position() == d->m_currentRenameSelectionBegin.position()
|
|
||||||
&& !cursor.hasSelection()) {
|
|
||||||
// Eat backspace at start of name when there is no selection
|
|
||||||
e->accept();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Qt::Key_Delete: {
|
|
||||||
if (cursor.position() == d->m_currentRenameSelectionEnd.position()
|
|
||||||
&& !cursor.hasSelection()) {
|
|
||||||
// Eat delete at end of name when there is no selection
|
|
||||||
e->accept();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} // switch
|
|
||||||
|
|
||||||
startRename();
|
|
||||||
|
|
||||||
bool wantEditBlock = (cursor.position() >= d->m_currentRenameSelectionBegin.position()
|
|
||||||
&& cursor.position() <= d->m_currentRenameSelectionEnd.position());
|
|
||||||
|
|
||||||
if (wantEditBlock) {
|
|
||||||
// possible change inside rename selection
|
|
||||||
if (d->m_firstRenameChange)
|
|
||||||
cursor.beginEditBlock();
|
|
||||||
else
|
|
||||||
cursor.joinPreviousEditBlock();
|
|
||||||
d->m_firstRenameChange = false;
|
|
||||||
}
|
|
||||||
TextEditor::BaseTextEditorWidget::keyPressEvent(e);
|
|
||||||
if (wantEditBlock)
|
|
||||||
cursor.endEditBlock();
|
|
||||||
finishRename();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::IEditor *CPPEditor::duplicate()
|
Core::IEditor *CPPEditor::duplicate()
|
||||||
@@ -1559,9 +1370,7 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
|
|||||||
convertPosition(position(), &line, &column);
|
convertPosition(position(), &line, &column);
|
||||||
|
|
||||||
QList<QTextEdit::ExtraSelection> unusedSelections;
|
QList<QTextEdit::ExtraSelection> unusedSelections;
|
||||||
|
QList<QTextEdit::ExtraSelection> selections;
|
||||||
d->m_renameSelections.clear();
|
|
||||||
d->m_currentRenameSelection = d->NoCurrentRenameSelection;
|
|
||||||
|
|
||||||
// We can use the semanticInfo's snapshot (and avoid locking), but not its
|
// We can use the semanticInfo's snapshot (and avoid locking), but not its
|
||||||
// document, since it doesn't contain expanded macros.
|
// document, since it doesn't contain expanded macros.
|
||||||
@@ -1584,21 +1393,21 @@ void CPPEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uses.size() == 1) {
|
if (uses.size() == 1) {
|
||||||
if (!CppTools::isOwnershipRAIIType(it.key(), context)) {
|
if (!CppTools::isOwnershipRAIIType(it.key(), context))
|
||||||
// it's an unused declaration
|
unusedSelections << createSelectionsFromUses(uses); // unused declaration
|
||||||
highlightUses(uses, &unusedSelections);
|
} else if (good && selections.isEmpty()) {
|
||||||
}
|
selections << createSelectionsFromUses(uses);
|
||||||
} else if (good && d->m_renameSelections.isEmpty()) {
|
|
||||||
highlightUses(uses, &d->m_renameSelections);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setExtraSelections(UnusedSymbolSelection, unusedSelections);
|
setExtraSelections(UnusedSymbolSelection, unusedSelections);
|
||||||
|
|
||||||
if (!d->m_renameSelections.isEmpty())
|
if (!selections.isEmpty()) {
|
||||||
setExtraSelections(CodeSemanticsSelection, d->m_renameSelections); // ###
|
setExtraSelections(CodeSemanticsSelection, selections);
|
||||||
else
|
d->m_localRenaming.updateLocalUseSelections(selections);
|
||||||
|
} else {
|
||||||
markSymbols(textCursor(), semanticInfo);
|
markSymbols(textCursor(), semanticInfo);
|
||||||
|
}
|
||||||
|
|
||||||
d->m_lastSemanticInfo.forced = false; // clear the forced flag
|
d->m_lastSemanticInfo.forced = false; // clear the forced flag
|
||||||
|
|
||||||
@@ -1775,6 +1584,16 @@ void CPPEditorWidget::abortDeclDefLink()
|
|||||||
d->m_declDefLink.clear();
|
d->m_declDefLink.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPPEditorWidget::onLocalRenamingFinished()
|
||||||
|
{
|
||||||
|
semanticRehighlight(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPPEditorWidget::onLocalRenamingProcessKeyPressNormally(QKeyEvent *e)
|
||||||
|
{
|
||||||
|
BaseTextEditorWidget::keyPressEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
bool CPPEditorWidget::handleDocumentationComment(QKeyEvent *e)
|
bool CPPEditorWidget::handleDocumentationComment(QKeyEvent *e)
|
||||||
{
|
{
|
||||||
if (!d->m_commentsSettings.m_enableDoxygen
|
if (!d->m_commentsSettings.m_enableDoxygen
|
||||||
@@ -1866,6 +1685,11 @@ bool CPPEditorWidget::isStartOfDoxygenComment(const QTextCursor &cursor) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTextCharFormat CPPEditorWidget::textCharFormat(TextEditor::TextStyle category)
|
||||||
|
{
|
||||||
|
return baseTextDocument()->fontSettings().toTextCharFormat(category);
|
||||||
|
}
|
||||||
|
|
||||||
void CPPEditorWidget::onCommentsSettingsChanged(const CppTools::CommentsSettings &settings)
|
void CPPEditorWidget::onCommentsSettingsChanged(const CppTools::CommentsSettings &settings)
|
||||||
{
|
{
|
||||||
d->m_commentsSettings = settings;
|
d->m_commentsSettings = settings;
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include <texteditor/basetexteditor.h>
|
#include <texteditor/basetexteditor.h>
|
||||||
#include <texteditor/semantichighlighter.h>
|
#include <texteditor/semantichighlighter.h>
|
||||||
|
#include <texteditor/texteditorconstants.h>
|
||||||
|
|
||||||
#include <utils/qtcoverride.h>
|
#include <utils/qtcoverride.h>
|
||||||
#include <utils/uncommentselection.h>
|
#include <utils/uncommentselection.h>
|
||||||
@@ -171,6 +172,9 @@ private slots:
|
|||||||
void onCommentsSettingsChanged(const CppTools::CommentsSettings &settings);
|
void onCommentsSettingsChanged(const CppTools::CommentsSettings &settings);
|
||||||
void abortDeclDefLink();
|
void abortDeclDefLink();
|
||||||
|
|
||||||
|
void onLocalRenamingFinished();
|
||||||
|
void onLocalRenamingProcessKeyPressNormally(QKeyEvent *e);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool openCppEditorAt(const Link &, bool inNextSplit = false);
|
static bool openCppEditorAt(const Link &, bool inNextSplit = false);
|
||||||
|
|
||||||
@@ -185,15 +189,13 @@ private:
|
|||||||
const CPlusPlus::Macro *findCanonicalMacro(const QTextCursor &cursor,
|
const CPlusPlus::Macro *findCanonicalMacro(const QTextCursor &cursor,
|
||||||
CPlusPlus::Document::Ptr doc) const;
|
CPlusPlus::Document::Ptr doc) const;
|
||||||
|
|
||||||
|
QTextCharFormat textCharFormat(TextEditor::TextStyle category);
|
||||||
|
|
||||||
void markSymbols(const QTextCursor &tc, const CppTools::SemanticInfo &info);
|
void markSymbols(const QTextCursor &tc, const CppTools::SemanticInfo &info);
|
||||||
bool sortedOutline() const;
|
bool sortedOutline() const;
|
||||||
|
|
||||||
void highlightUses(const QList<TextEditor::HighlightingResult> &uses,
|
QList<QTextEdit::ExtraSelection> createSelectionsFromUses(
|
||||||
QList<QTextEdit::ExtraSelection> *selections);
|
const QList<TextEditor::HighlightingResult> &uses);
|
||||||
|
|
||||||
void startRename();
|
|
||||||
void finishRename();
|
|
||||||
void abortRename();
|
|
||||||
|
|
||||||
QModelIndex indexForPosition(int line, int column,
|
QModelIndex indexForPosition(int line, int column,
|
||||||
const QModelIndex &rootIndex = QModelIndex()) const;
|
const QModelIndex &rootIndex = QModelIndex()) const;
|
||||||
|
@@ -23,6 +23,7 @@ HEADERS += \
|
|||||||
cppincludehierarchymodel.h \
|
cppincludehierarchymodel.h \
|
||||||
cppincludehierarchytreeview.h \
|
cppincludehierarchytreeview.h \
|
||||||
cppinsertvirtualmethods.h \
|
cppinsertvirtualmethods.h \
|
||||||
|
cpplocalrenaming.h \
|
||||||
cppoutline.h \
|
cppoutline.h \
|
||||||
cpppreprocessordialog.h \
|
cpppreprocessordialog.h \
|
||||||
cppquickfix.h \
|
cppquickfix.h \
|
||||||
@@ -52,6 +53,7 @@ SOURCES += \
|
|||||||
cppincludehierarchymodel.cpp \
|
cppincludehierarchymodel.cpp \
|
||||||
cppincludehierarchytreeview.cpp \
|
cppincludehierarchytreeview.cpp \
|
||||||
cppinsertvirtualmethods.cpp \
|
cppinsertvirtualmethods.cpp \
|
||||||
|
cpplocalrenaming.cpp \
|
||||||
cppoutline.cpp \
|
cppoutline.cpp \
|
||||||
cpppreprocessordialog.cpp \
|
cpppreprocessordialog.cpp \
|
||||||
cppquickfix.cpp \
|
cppquickfix.cpp \
|
||||||
|
@@ -42,6 +42,7 @@ QtcPlugin {
|
|||||||
"cppincludehierarchytreeview.cpp", "cppincludehierarchytreeview.h",
|
"cppincludehierarchytreeview.cpp", "cppincludehierarchytreeview.h",
|
||||||
"cppinsertvirtualmethods.cpp",
|
"cppinsertvirtualmethods.cpp",
|
||||||
"cppinsertvirtualmethods.h",
|
"cppinsertvirtualmethods.h",
|
||||||
|
"cpplocalrenaming.cpp", "cpplocalrenaming.h",
|
||||||
"cppoutline.cpp", "cppoutline.h",
|
"cppoutline.cpp", "cppoutline.h",
|
||||||
"cpppreprocessordialog.cpp", "cpppreprocessordialog.h", "cpppreprocessordialog.ui",
|
"cpppreprocessordialog.cpp", "cpppreprocessordialog.h", "cpppreprocessordialog.ui",
|
||||||
"cppquickfix.cpp", "cppquickfix.h",
|
"cppquickfix.cpp", "cppquickfix.h",
|
||||||
|
335
src/plugins/cppeditor/cpplocalrenaming.cpp
Normal file
335
src/plugins/cppeditor/cpplocalrenaming.cpp
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "cpplocalrenaming.h"
|
||||||
|
|
||||||
|
#include <texteditor/basetexteditor.h>
|
||||||
|
#include <texteditor/fontsettings.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class CppEditor::Internal::CppLocalRenaming
|
||||||
|
\brief A helper class of CPPEditorWidget that implements renaming local usages.
|
||||||
|
|
||||||
|
\internal
|
||||||
|
|
||||||
|
Local use selections must be first set/updated with updateLocalUseSelections().
|
||||||
|
Afterwards the local renaming can be started with start(). The CPPEditorWidget
|
||||||
|
can then delegate work related to the local renaming mode to the handle*
|
||||||
|
functions.
|
||||||
|
|
||||||
|
\sa CppEditor::Internal::CPPEditorWidget
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void modifyCursorSelection(QTextCursor &cursor, int position, int anchor)
|
||||||
|
{
|
||||||
|
cursor.setPosition(anchor);
|
||||||
|
cursor.setPosition(position, QTextCursor::KeepAnchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
namespace CppEditor {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
CppLocalRenaming::CppLocalRenaming(TextEditor::BaseTextEditorWidget *editorWidget)
|
||||||
|
: m_editorWidget(editorWidget)
|
||||||
|
, m_modifyingSelections(false)
|
||||||
|
, m_renameSelectionChanged(false)
|
||||||
|
, m_firstRenameChangeExpected(false)
|
||||||
|
{
|
||||||
|
forgetRenamingSelection();
|
||||||
|
connect(m_editorWidget->document(), SIGNAL(contentsChange(int,int,int)),
|
||||||
|
this, SLOT(onContentsChangeOfEditorWidgetDocument(int,int,int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::updateLocalUseSelections(const QList<QTextEdit::ExtraSelection> &selections)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(!isActive(), return);
|
||||||
|
m_selections = selections;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppLocalRenaming::start()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
|
||||||
|
if (findRenameSelection(m_editorWidget->textCursor().position())) {
|
||||||
|
updateRenamingSelectionFormat(textCharFormat(TextEditor::C_OCCURRENCES_RENAME));
|
||||||
|
m_firstRenameChangeExpected = true;
|
||||||
|
updateEditorWidgetWithSelections();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppLocalRenaming::handlePaste()
|
||||||
|
{
|
||||||
|
if (!isActive())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
startRenameChange();
|
||||||
|
m_editorWidget->BaseTextEditorWidget::paste();
|
||||||
|
finishRenameChange();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppLocalRenaming::handleCut()
|
||||||
|
{
|
||||||
|
if (!isActive())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
startRenameChange();
|
||||||
|
m_editorWidget->BaseTextEditorWidget::paste();
|
||||||
|
finishRenameChange();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppLocalRenaming::handleSelectAll()
|
||||||
|
{
|
||||||
|
if (!isActive())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QTextCursor cursor = m_editorWidget->textCursor();
|
||||||
|
if (!isWithinRenameSelection(cursor.position()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
modifyCursorSelection(cursor, renameSelectionBegin(), renameSelectionEnd());
|
||||||
|
m_editorWidget->setTextCursor(cursor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppLocalRenaming::isActive() const
|
||||||
|
{
|
||||||
|
return m_renameSelectionIndex != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppLocalRenaming::handleKeyPressEvent(QKeyEvent *e)
|
||||||
|
{
|
||||||
|
if (!isActive())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QTextCursor cursor = m_editorWidget->textCursor();
|
||||||
|
const int cursorPosition = cursor.position();
|
||||||
|
const QTextCursor::MoveMode moveMode = (e->modifiers() & Qt::ShiftModifier)
|
||||||
|
? QTextCursor::KeepAnchor
|
||||||
|
: QTextCursor::MoveAnchor;
|
||||||
|
|
||||||
|
switch (e->key()) {
|
||||||
|
case Qt::Key_Enter:
|
||||||
|
case Qt::Key_Return:
|
||||||
|
case Qt::Key_Escape:
|
||||||
|
stop();
|
||||||
|
e->accept();
|
||||||
|
return true;
|
||||||
|
case Qt::Key_Home: {
|
||||||
|
// Send home to start of name when within the name and not at the start
|
||||||
|
if (renameSelectionBegin() < cursorPosition && cursorPosition <= renameSelectionEnd()) {
|
||||||
|
cursor.setPosition(renameSelectionBegin(), moveMode);
|
||||||
|
m_editorWidget->setTextCursor(cursor);
|
||||||
|
e->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Qt::Key_End: {
|
||||||
|
// Send end to end of name when within the name and not at the end
|
||||||
|
if (renameSelectionBegin() <= cursorPosition && cursorPosition < renameSelectionEnd()) {
|
||||||
|
cursor.setPosition(renameSelectionEnd(), moveMode);
|
||||||
|
m_editorWidget->setTextCursor(cursor);
|
||||||
|
e->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Qt::Key_Backspace: {
|
||||||
|
if (cursorPosition == renameSelectionBegin() && !cursor.hasSelection()) {
|
||||||
|
// Eat backspace at start of name when there is no selection
|
||||||
|
e->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Qt::Key_Delete: {
|
||||||
|
if (cursorPosition == renameSelectionEnd() && !cursor.hasSelection()) {
|
||||||
|
// Eat delete at end of name when there is no selection
|
||||||
|
e->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // switch
|
||||||
|
|
||||||
|
startRenameChange();
|
||||||
|
|
||||||
|
const bool wantEditBlock = isWithinRenameSelection(cursorPosition);
|
||||||
|
if (wantEditBlock) {
|
||||||
|
if (m_firstRenameChangeExpected) // Change inside rename selection
|
||||||
|
cursor.beginEditBlock();
|
||||||
|
else
|
||||||
|
cursor.joinPreviousEditBlock();
|
||||||
|
m_firstRenameChangeExpected = false;
|
||||||
|
}
|
||||||
|
emit processKeyPressNormally(e);
|
||||||
|
if (wantEditBlock)
|
||||||
|
cursor.endEditBlock();
|
||||||
|
finishRenameChange();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextEdit::ExtraSelection &CppLocalRenaming::renameSelection()
|
||||||
|
{
|
||||||
|
return m_selections[m_renameSelectionIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::updateRenamingSelectionCursor(const QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(isActive(), return);
|
||||||
|
renameSelection().cursor = cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::updateRenamingSelectionFormat(const QTextCharFormat &format)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(isActive(), return);
|
||||||
|
renameSelection().format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::forgetRenamingSelection()
|
||||||
|
{
|
||||||
|
m_renameSelectionIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppLocalRenaming::isWithinRenameSelection(int position)
|
||||||
|
{
|
||||||
|
return renameSelectionBegin() <= position && position <= renameSelectionEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppLocalRenaming::findRenameSelection(int cursorPosition)
|
||||||
|
{
|
||||||
|
for (int i = 0, total = m_selections.size(); i < total; ++i) {
|
||||||
|
const QTextEdit::ExtraSelection &sel = m_selections.at(i);
|
||||||
|
if (sel.cursor.position() <= cursorPosition && cursorPosition <= sel.cursor.anchor()) {
|
||||||
|
m_renameSelectionIndex = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::changeOtherSelectionsText(const QString &text)
|
||||||
|
{
|
||||||
|
for (int i = 0, total = m_selections.size(); i < total; ++i) {
|
||||||
|
if (i == m_renameSelectionIndex)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QTextEdit::ExtraSelection &selection = m_selections[i];
|
||||||
|
const int pos = selection.cursor.selectionStart();
|
||||||
|
selection.cursor.removeSelectedText();
|
||||||
|
selection.cursor.insertText(text);
|
||||||
|
selection.cursor.setPosition(pos, QTextCursor::KeepAnchor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::onContentsChangeOfEditorWidgetDocument(int position,
|
||||||
|
int charsRemoved,
|
||||||
|
int charsAdded)
|
||||||
|
{
|
||||||
|
Q_UNUSED(charsRemoved)
|
||||||
|
|
||||||
|
if (!isActive() || m_modifyingSelections)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (position + charsAdded == renameSelectionBegin()) // Insert at beginning, expand cursor
|
||||||
|
modifyCursorSelection(renameSelection().cursor, position, renameSelectionEnd());
|
||||||
|
|
||||||
|
// Keep in mind that cursor position and anchor move automatically
|
||||||
|
m_renameSelectionChanged = isWithinRenameSelection(position)
|
||||||
|
&& isWithinRenameSelection(position + charsAdded);
|
||||||
|
|
||||||
|
if (!m_renameSelectionChanged)
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::startRenameChange()
|
||||||
|
{
|
||||||
|
m_renameSelectionChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::updateEditorWidgetWithSelections()
|
||||||
|
{
|
||||||
|
m_editorWidget->setExtraSelections(TextEditor::BaseTextEditorWidget::CodeSemanticsSelection,
|
||||||
|
m_selections);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextCharFormat CppLocalRenaming::textCharFormat(TextEditor::TextStyle category) const
|
||||||
|
{
|
||||||
|
return m_editorWidget->baseTextDocument()->fontSettings().toTextCharFormat(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::finishRenameChange()
|
||||||
|
{
|
||||||
|
if (!m_renameSelectionChanged)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_modifyingSelections = true;
|
||||||
|
|
||||||
|
QTextCursor cursor = m_editorWidget->textCursor();
|
||||||
|
cursor.joinPreviousEditBlock();
|
||||||
|
|
||||||
|
modifyCursorSelection(cursor, renameSelectionBegin(), renameSelectionEnd());
|
||||||
|
updateRenamingSelectionCursor(cursor);
|
||||||
|
changeOtherSelectionsText(cursor.selectedText());
|
||||||
|
updateEditorWidgetWithSelections();
|
||||||
|
|
||||||
|
cursor.endEditBlock();
|
||||||
|
|
||||||
|
m_modifyingSelections = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppLocalRenaming::stop()
|
||||||
|
{
|
||||||
|
if (!isActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
updateRenamingSelectionFormat(textCharFormat(TextEditor::C_OCCURRENCES));
|
||||||
|
updateEditorWidgetWithSelections();
|
||||||
|
forgetRenamingSelection();
|
||||||
|
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace CppEditor
|
109
src/plugins/cppeditor/cpplocalrenaming.h
Normal file
109
src/plugins/cppeditor/cpplocalrenaming.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CPPLOCALRENAMING
|
||||||
|
#define CPPLOCALRENAMING
|
||||||
|
|
||||||
|
#include <texteditor/texteditorconstants.h>
|
||||||
|
|
||||||
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
namespace TextEditor { class BaseTextEditorWidget; }
|
||||||
|
|
||||||
|
namespace CppEditor {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class CppLocalRenaming : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(CppLocalRenaming)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CppLocalRenaming(TextEditor::BaseTextEditorWidget *editorWidget);
|
||||||
|
|
||||||
|
void updateLocalUseSelections(const QList<QTextEdit::ExtraSelection> &selections);
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
bool isActive() const;
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
// Delegates for the editor widget
|
||||||
|
bool handlePaste();
|
||||||
|
bool handleCut();
|
||||||
|
bool handleSelectAll();
|
||||||
|
|
||||||
|
// E.g. limit navigation keys to selection, stop() on Esc/Return or delegate
|
||||||
|
// to BaseTextEditorWidget::keyPressEvent()
|
||||||
|
bool handleKeyPressEvent(QKeyEvent *e);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
void processKeyPressNormally(QKeyEvent *e);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onContentsChangeOfEditorWidgetDocument(int position, int charsRemoved, int charsAdded);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CppLocalRenaming();
|
||||||
|
|
||||||
|
// The "rename selection" is the local use selection on which the user started the renaming
|
||||||
|
bool findRenameSelection(int cursorPosition);
|
||||||
|
void forgetRenamingSelection();
|
||||||
|
bool isWithinRenameSelection(int position);
|
||||||
|
|
||||||
|
QTextEdit::ExtraSelection &renameSelection();
|
||||||
|
int renameSelectionBegin() { return renameSelection().cursor.position(); }
|
||||||
|
int renameSelectionEnd() { return renameSelection().cursor.anchor(); }
|
||||||
|
|
||||||
|
void updateRenamingSelectionCursor(const QTextCursor &cursor);
|
||||||
|
void updateRenamingSelectionFormat(const QTextCharFormat &format);
|
||||||
|
|
||||||
|
void changeOtherSelectionsText(const QString &text);
|
||||||
|
|
||||||
|
void startRenameChange();
|
||||||
|
void finishRenameChange();
|
||||||
|
|
||||||
|
void updateEditorWidgetWithSelections();
|
||||||
|
|
||||||
|
QTextCharFormat textCharFormat(TextEditor::TextStyle category) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextEditor::BaseTextEditorWidget *m_editorWidget;
|
||||||
|
|
||||||
|
QList<QTextEdit::ExtraSelection> m_selections;
|
||||||
|
int m_renameSelectionIndex;
|
||||||
|
bool m_modifyingSelections;
|
||||||
|
bool m_renameSelectionChanged;
|
||||||
|
bool m_firstRenameChangeExpected;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace CppEditor
|
||||||
|
|
||||||
|
#endif // CPPLOCALRENAMING
|
Reference in New Issue
Block a user