Commit bed88818 authored by Alexandru Croitor's avatar Alexandru Croitor Committed by Nikolai Kosjar

C++: Implement context-aware expand / shrink selection actions.

Implement selection expanding / shrinking, that is aware of C++
semantics, thus giving smart selection changing.

Change-Id: I1386a20597fa6bb85c3aa0d8ddfb87cdb3fd7c38
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@theqtcompany.com>
parent 8bfdc82c
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include <cpptools/cppcompletionassistprovider.h> #include <cpptools/cppcompletionassistprovider.h>
#include <cpptools/cppeditoroutline.h> #include <cpptools/cppeditoroutline.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <cpptools/cppselectionchanger.h>
#include <cpptools/cppsemanticinfo.h> #include <cpptools/cppsemanticinfo.h>
#include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolsconstants.h>
#include <cpptools/cpptoolsplugin.h> #include <cpptools/cpptoolsplugin.h>
...@@ -55,6 +56,7 @@ ...@@ -55,6 +56,7 @@
#include <cpptools/cppworkingcopy.h> #include <cpptools/cppworkingcopy.h>
#include <cpptools/symbolfinder.h> #include <cpptools/symbolfinder.h>
#include <texteditor/behaviorsettings.h>
#include <texteditor/completionsettings.h> #include <texteditor/completionsettings.h>
#include <texteditor/convenience.h> #include <texteditor/convenience.h>
#include <texteditor/textdocument.h> #include <texteditor/textdocument.h>
...@@ -119,6 +121,8 @@ public: ...@@ -119,6 +121,8 @@ public:
QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor; QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor;
QToolButton *m_preprocessorButton; QToolButton *m_preprocessorButton;
CppSelectionChanger m_cppSelectionChanger;
}; };
CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q) CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
...@@ -130,6 +134,7 @@ CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q) ...@@ -130,6 +134,7 @@ CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
, m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q)) , m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q))
, m_followSymbolUnderCursor(new FollowSymbolUnderCursor(q)) , m_followSymbolUnderCursor(new FollowSymbolUnderCursor(q))
, m_preprocessorButton(0) , m_preprocessorButton(0)
, m_cppSelectionChanger()
{ {
} }
...@@ -201,6 +206,9 @@ void CppEditorWidget::finalizeInitialization() ...@@ -201,6 +206,9 @@ void CppEditorWidget::finalizeInitialization()
connect(this, &CppEditorWidget::cursorPositionChanged, [this]() { connect(this, &CppEditorWidget::cursorPositionChanged, [this]() {
if (!d->m_localRenaming.isActive()) if (!d->m_localRenaming.isActive())
d->m_useSelectionsUpdater.scheduleUpdate(); d->m_useSelectionsUpdater.scheduleUpdate();
// Notify selection expander about the changed cursor.
d->m_cppSelectionChanger.onCursorPositionChanged(textCursor());
}); });
// Tool bar creation // Tool bar creation
...@@ -328,6 +336,44 @@ void CppEditorWidget::renameUsages(const QString &replacement) ...@@ -328,6 +336,44 @@ void CppEditorWidget::renameUsages(const QString &replacement)
} }
} }
bool CppEditorWidget::selectBlockUp()
{
if (!behaviorSettings().m_smartSelectionChanging)
return TextEditorWidget::selectBlockUp();
QTextCursor cursor = textCursor();
d->m_cppSelectionChanger.startChangeSelection();
const bool changed =
d->m_cppSelectionChanger.changeSelection(
CppSelectionChanger::ExpandSelection,
cursor,
d->m_lastSemanticInfo.doc);
if (changed)
setTextCursor(cursor);
d->m_cppSelectionChanger.stopChangeSelection();
return changed;
}
bool CppEditorWidget::selectBlockDown()
{
if (!behaviorSettings().m_smartSelectionChanging)
return TextEditorWidget::selectBlockDown();
QTextCursor cursor = textCursor();
d->m_cppSelectionChanger.startChangeSelection();
const bool changed =
d->m_cppSelectionChanger.changeSelection(
CppSelectionChanger::ShrinkSelection,
cursor,
d->m_lastSemanticInfo.doc);
if (changed)
setTextCursor(cursor);
d->m_cppSelectionChanger.stopChangeSelection();
return changed;
}
void CppEditorWidget::renameSymbolUnderCursor() void CppEditorWidget::renameSymbolUnderCursor()
{ {
d->m_useSelectionsUpdater.abortSchedule(); d->m_useSelectionsUpdater.abortSchedule();
......
...@@ -92,6 +92,9 @@ public slots: ...@@ -92,6 +92,9 @@ public slots:
void renameSymbolUnderCursor(); void renameSymbolUnderCursor();
void renameUsages(const QString &replacement = QString()); void renameUsages(const QString &replacement = QString());
bool selectBlockUp() override;
bool selectBlockDown() override;
protected: protected:
bool event(QEvent *e) override; bool event(QEvent *e) override;
void contextMenuEvent(QContextMenuEvent *) override; void contextMenuEvent(QContextMenuEvent *) override;
......
This diff is collapsed.
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#ifndef CPPSELECTIONCHANGER_H
#define CPPSELECTIONCHANGER_H
#include "cpptools_global.h"
#include <cplusplus/ASTPath.h>
#include <cplusplus/CppDocument.h>
#include <cplusplus/TranslationUnit.h>
#include <QObject>
#include <QTextCursor>
namespace CppTools {
class ASTNodePositions {
public:
ASTNodePositions() {}
ASTNodePositions(CPlusPlus::AST *_ast) : ast(_ast) {}
operator bool() const { return ast; }
CPlusPlus::AST *ast = 0;
unsigned firstTokenIndex = 0;
unsigned lastTokenIndex = 0;
unsigned secondToLastTokenIndex = 0;
int astPosStart = -1;
int astPosEnd = -1;
};
class CPPTOOLS_EXPORT CppSelectionChanger : public QObject
{
Q_OBJECT
public:
explicit CppSelectionChanger(QObject *parent = 0);
enum Direction {
ExpandSelection,
ShrinkSelection
};
enum NodeIndexAndStepState {
NodeIndexAndStepNotSet,
NodeIndexAndStepWholeDocument,
};
bool changeSelection(Direction direction,
QTextCursor &cursorToModify,
const CPlusPlus::Document::Ptr doc);
void startChangeSelection();
void stopChangeSelection();
public slots:
void onCursorPositionChanged(const QTextCursor &newCursor);
protected slots:
void fineTuneForStatementPositions(unsigned firstParensTokenIndex,
unsigned lastParensTokenIndex,
ASTNodePositions &positions) const;
private:
bool performSelectionChange(QTextCursor &cursorToModify);
ASTNodePositions getASTPositions(CPlusPlus::AST *ast, const QTextCursor &cursor) const;
void updateCursorSelection(QTextCursor &cursorToModify, ASTNodePositions positions);
int possibleASTStepCount(CPlusPlus::AST *ast) const;
int currentASTStep() const;
ASTNodePositions findNextASTStepPositions(const QTextCursor &cursor);
void fineTuneASTNodePositions(ASTNodePositions &positions) const;
ASTNodePositions getFineTunedASTPositions(CPlusPlus::AST *ast, const QTextCursor &cursor) const;
int getFirstCurrentStepForASTNode(CPlusPlus::AST *ast) const;
bool isLastPossibleStepForASTNode(CPlusPlus::AST *ast) const;
ASTNodePositions findRelevantASTPositionsFromCursor(const QList<CPlusPlus::AST *> &astPath,
const QTextCursor &cursor,
int startingFromNodeIndex = -1);
ASTNodePositions findRelevantASTPositionsFromCursorWhenNodeIndexNotSet(
const QList<CPlusPlus::AST *> astPath,
const QTextCursor &cursor);
ASTNodePositions findRelevantASTPositionsFromCursorWhenWholeDocumentSelected(
const QList<CPlusPlus::AST *> astPath,
const QTextCursor &cursor);
ASTNodePositions findRelevantASTPositionsFromCursorFromPreviousNodeIndex(
const QList<CPlusPlus::AST *> astPath,
const QTextCursor &cursor);
bool shouldSkipASTNodeBasedOnPosition(const ASTNodePositions &positions,
const QTextCursor &cursor) const;
void setNodeIndexAndStep(NodeIndexAndStepState state);
int getTokenStartCursorPosition(unsigned tokenIndex, const QTextCursor &cursor) const;
int getTokenEndCursorPosition(unsigned tokenIndex, const QTextCursor &cursor) const;
void printTokenDebugInfo(unsigned tokenIndex, const QTextCursor &cursor, QString prefix) const;
QTextCursor m_initialChangeSelectionCursor;
QTextCursor m_workingCursor;
CPlusPlus::Document::Ptr m_doc;
CPlusPlus::TranslationUnit *m_unit;
Direction m_direction;
int m_changeSelectionNodeIndex;
int m_nodeCurrentStep;
bool m_inChangeSelection;
};
} // namespace CppTools
#endif // CPPSELECTIONCHANGER_H
...@@ -43,6 +43,7 @@ HEADERS += \ ...@@ -43,6 +43,7 @@ HEADERS += \
cppprojectfile.h \ cppprojectfile.h \
cppqtstyleindenter.h \ cppqtstyleindenter.h \
cpprefactoringchanges.h \ cpprefactoringchanges.h \
cppselectionchanger.h \
cppsemanticinfo.h \ cppsemanticinfo.h \
cppsemanticinfoupdater.h \ cppsemanticinfoupdater.h \
cppsourceprocessor.h \ cppsourceprocessor.h \
...@@ -117,6 +118,7 @@ SOURCES += \ ...@@ -117,6 +118,7 @@ SOURCES += \
cppprojectfile.cpp \ cppprojectfile.cpp \
cppqtstyleindenter.cpp \ cppqtstyleindenter.cpp \
cpprefactoringchanges.cpp \ cpprefactoringchanges.cpp \
cppselectionchanger.cpp \
cppsemanticinfo.cpp \ cppsemanticinfo.cpp \
cppsemanticinfoupdater.cpp \ cppsemanticinfoupdater.cpp \
cppsourceprocessor.cpp \ cppsourceprocessor.cpp \
......
...@@ -66,6 +66,7 @@ QtcPlugin { ...@@ -66,6 +66,7 @@ QtcPlugin {
"cppprojectfile.cpp", "cppprojectfile.h", "cppprojectfile.cpp", "cppprojectfile.h",
"cppqtstyleindenter.cpp", "cppqtstyleindenter.h", "cppqtstyleindenter.cpp", "cppqtstyleindenter.h",
"cpprefactoringchanges.cpp", "cpprefactoringchanges.h", "cpprefactoringchanges.cpp", "cpprefactoringchanges.h",
"cppselectionchanger.cpp", "cppselectionchanger.h",
"cppsemanticinfo.cpp", "cppsemanticinfo.h", "cppsemanticinfo.cpp", "cppsemanticinfo.h",
"cppsemanticinfoupdater.cpp", "cppsemanticinfoupdater.h", "cppsemanticinfoupdater.cpp", "cppsemanticinfoupdater.h",
"cppsourceprocessor.cpp", "cppsourceprocessor.h", "cppsourceprocessor.cpp", "cppsourceprocessor.h",
......
...@@ -37,6 +37,7 @@ static const char constrainTooltips[] = "ConstrainTooltips"; ...@@ -37,6 +37,7 @@ static const char constrainTooltips[] = "ConstrainTooltips";
static const char camelCaseNavigationKey[] = "CamelCaseNavigation"; static const char camelCaseNavigationKey[] = "CamelCaseNavigation";
static const char keyboardTooltips[] = "KeyboardTooltips"; static const char keyboardTooltips[] = "KeyboardTooltips";
static const char groupPostfix[] = "BehaviorSettings"; static const char groupPostfix[] = "BehaviorSettings";
static const char smartSelectionChanging[] = "SmartSelectionChanging";
namespace TextEditor { namespace TextEditor {
...@@ -46,7 +47,8 @@ BehaviorSettings::BehaviorSettings() : ...@@ -46,7 +47,8 @@ BehaviorSettings::BehaviorSettings() :
m_scrollWheelZooming(true), m_scrollWheelZooming(true),
m_constrainHoverTooltips(false), m_constrainHoverTooltips(false),
m_camelCaseNavigation(true), m_camelCaseNavigation(true),
m_keyboardTooltips(false) m_keyboardTooltips(false),
m_smartSelectionChanging(true)
{ {
} }
...@@ -69,6 +71,7 @@ void BehaviorSettings::toMap(const QString &prefix, QVariantMap *map) const ...@@ -69,6 +71,7 @@ void BehaviorSettings::toMap(const QString &prefix, QVariantMap *map) const
map->insert(prefix + QLatin1String(constrainTooltips), m_constrainHoverTooltips); map->insert(prefix + QLatin1String(constrainTooltips), m_constrainHoverTooltips);
map->insert(prefix + QLatin1String(camelCaseNavigationKey), m_camelCaseNavigation); map->insert(prefix + QLatin1String(camelCaseNavigationKey), m_camelCaseNavigation);
map->insert(prefix + QLatin1String(keyboardTooltips), m_keyboardTooltips); map->insert(prefix + QLatin1String(keyboardTooltips), m_keyboardTooltips);
map->insert(prefix + QLatin1String(smartSelectionChanging), m_smartSelectionChanging);
} }
void BehaviorSettings::fromMap(const QString &prefix, const QVariantMap &map) void BehaviorSettings::fromMap(const QString &prefix, const QVariantMap &map)
...@@ -85,6 +88,9 @@ void BehaviorSettings::fromMap(const QString &prefix, const QVariantMap &map) ...@@ -85,6 +88,9 @@ void BehaviorSettings::fromMap(const QString &prefix, const QVariantMap &map)
map.value(prefix + QLatin1String(camelCaseNavigationKey), m_camelCaseNavigation).toBool(); map.value(prefix + QLatin1String(camelCaseNavigationKey), m_camelCaseNavigation).toBool();
m_keyboardTooltips = m_keyboardTooltips =
map.value(prefix + QLatin1String(keyboardTooltips), m_keyboardTooltips).toBool(); map.value(prefix + QLatin1String(keyboardTooltips), m_keyboardTooltips).toBool();
m_smartSelectionChanging =
map.value(prefix + QLatin1String(smartSelectionChanging), m_smartSelectionChanging)
.toBool();
} }
bool BehaviorSettings::equals(const BehaviorSettings &ds) const bool BehaviorSettings::equals(const BehaviorSettings &ds) const
...@@ -95,6 +101,7 @@ bool BehaviorSettings::equals(const BehaviorSettings &ds) const ...@@ -95,6 +101,7 @@ bool BehaviorSettings::equals(const BehaviorSettings &ds) const
&& m_constrainHoverTooltips == ds.m_constrainHoverTooltips && m_constrainHoverTooltips == ds.m_constrainHoverTooltips
&& m_camelCaseNavigation == ds.m_camelCaseNavigation && m_camelCaseNavigation == ds.m_camelCaseNavigation
&& m_keyboardTooltips == ds.m_keyboardTooltips && m_keyboardTooltips == ds.m_keyboardTooltips
&& m_smartSelectionChanging == ds.m_smartSelectionChanging
; ;
} }
......
...@@ -59,6 +59,7 @@ public: ...@@ -59,6 +59,7 @@ public:
bool m_constrainHoverTooltips; bool m_constrainHoverTooltips;
bool m_camelCaseNavigation; bool m_camelCaseNavigation;
bool m_keyboardTooltips; bool m_keyboardTooltips;
bool m_smartSelectionChanging;
}; };
inline bool operator==(const BehaviorSettings &t1, const BehaviorSettings &t2) { return t1.equals(t2); } inline bool operator==(const BehaviorSettings &t1, const BehaviorSettings &t2) { return t1.equals(t2); }
......
...@@ -111,6 +111,8 @@ BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent) ...@@ -111,6 +111,8 @@ BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent)
this, &BehaviorSettingsWidget::slotBehaviorSettingsChanged); this, &BehaviorSettingsWidget::slotBehaviorSettingsChanged);
connect(d->m_ui.keyboardTooltips, &QAbstractButton::clicked, connect(d->m_ui.keyboardTooltips, &QAbstractButton::clicked,
this, &BehaviorSettingsWidget::slotBehaviorSettingsChanged); this, &BehaviorSettingsWidget::slotBehaviorSettingsChanged);
connect(d->m_ui.smartSelectionChanging, &QAbstractButton::clicked,
this, &BehaviorSettingsWidget::slotBehaviorSettingsChanged);
} }
BehaviorSettingsWidget::~BehaviorSettingsWidget() BehaviorSettingsWidget::~BehaviorSettingsWidget()
...@@ -198,6 +200,7 @@ void BehaviorSettingsWidget::setAssignedBehaviorSettings(const BehaviorSettings ...@@ -198,6 +200,7 @@ void BehaviorSettingsWidget::setAssignedBehaviorSettings(const BehaviorSettings
d->m_ui.constrainTooltipsBox->setCurrentIndex(behaviorSettings.m_constrainHoverTooltips ? 1 : 0); d->m_ui.constrainTooltipsBox->setCurrentIndex(behaviorSettings.m_constrainHoverTooltips ? 1 : 0);
d->m_ui.camelCaseNavigation->setChecked(behaviorSettings.m_camelCaseNavigation); d->m_ui.camelCaseNavigation->setChecked(behaviorSettings.m_camelCaseNavigation);
d->m_ui.keyboardTooltips->setChecked(behaviorSettings.m_keyboardTooltips); d->m_ui.keyboardTooltips->setChecked(behaviorSettings.m_keyboardTooltips);
d->m_ui.smartSelectionChanging->setChecked(behaviorSettings.m_smartSelectionChanging);
updateConstrainTooltipsBoxTooltip(); updateConstrainTooltipsBoxTooltip();
} }
...@@ -209,6 +212,7 @@ void BehaviorSettingsWidget::assignedBehaviorSettings(BehaviorSettings *behavior ...@@ -209,6 +212,7 @@ void BehaviorSettingsWidget::assignedBehaviorSettings(BehaviorSettings *behavior
behaviorSettings->m_constrainHoverTooltips = (d->m_ui.constrainTooltipsBox->currentIndex() == 1); behaviorSettings->m_constrainHoverTooltips = (d->m_ui.constrainTooltipsBox->currentIndex() == 1);
behaviorSettings->m_camelCaseNavigation = d->m_ui.camelCaseNavigation->isChecked(); behaviorSettings->m_camelCaseNavigation = d->m_ui.camelCaseNavigation->isChecked();
behaviorSettings->m_keyboardTooltips = d->m_ui.keyboardTooltips->isChecked(); behaviorSettings->m_keyboardTooltips = d->m_ui.keyboardTooltips->isChecked();
behaviorSettings->m_smartSelectionChanging = d->m_ui.smartSelectionChanging->isChecked();
} }
void BehaviorSettingsWidget::setAssignedExtraEncodingSettings( void BehaviorSettingsWidget::setAssignedExtraEncodingSettings(
......
...@@ -357,6 +357,16 @@ Specifies how backspace interacts with indentation. ...@@ -357,6 +357,16 @@ Specifies how backspace interacts with indentation.
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="smartSelectionChanging">
<property name="toolTip">
<string>Using Select Block Up / Down actions will now provide smarter selections.</string>
</property>
<property name="text">
<string>Enable smart selection changing</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="keyboardTooltips"> <widget class="QCheckBox" name="keyboardTooltips">
<property name="toolTip"> <property name="toolTip">
......
...@@ -61,5 +61,13 @@ QString textAt(QTextCursor tc, int pos, int length) ...@@ -61,5 +61,13 @@ QString textAt(QTextCursor tc, int pos, int length)
return tc.selectedText().replace(QChar::ParagraphSeparator, QLatin1Char('\n')); return tc.selectedText().replace(QChar::ParagraphSeparator, QLatin1Char('\n'));
} }
QTextCursor flippedCursor(const QTextCursor &cursor)
{
QTextCursor flipped = cursor;
flipped.clearSelection();
flipped.setPosition(cursor.anchor(), QTextCursor::KeepAnchor);
return flipped;
}
} // Util } // Util
} // TextEditor } // TextEditor
...@@ -44,6 +44,8 @@ TEXTEDITOR_EXPORT bool convertPosition(const QTextDocument *document, ...@@ -44,6 +44,8 @@ TEXTEDITOR_EXPORT bool convertPosition(const QTextDocument *document,
TEXTEDITOR_EXPORT QString textAt(QTextCursor tc, int pos, int length); TEXTEDITOR_EXPORT QString textAt(QTextCursor tc, int pos, int length);
TEXTEDITOR_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
} // Util } // Util
} // TextEditor } // TextEditor
......
...@@ -1300,14 +1300,6 @@ void TextEditorWidget::gotoNextWordCamelCaseWithSelection() ...@@ -1300,14 +1300,6 @@ void TextEditorWidget::gotoNextWordCamelCaseWithSelection()
setTextCursor(c); setTextCursor(c);
} }
static QTextCursor flippedCursor(const QTextCursor &cursor)
{
QTextCursor flipped = cursor;
flipped.clearSelection();
flipped.setPosition(cursor.anchor(), QTextCursor::KeepAnchor);
return flipped;
}
bool TextEditorWidget::selectBlockUp() bool TextEditorWidget::selectBlockUp()
{ {
QTextCursor cursor = textCursor(); QTextCursor cursor = textCursor();
...@@ -1321,7 +1313,7 @@ bool TextEditorWidget::selectBlockUp() ...@@ -1321,7 +1313,7 @@ bool TextEditorWidget::selectBlockUp()
if (!TextBlockUserData::findNextClosingParenthesis(&cursor, true)) if (!TextBlockUserData::findNextClosingParenthesis(&cursor, true))
return false; return false;
setTextCursor(flippedCursor(cursor)); setTextCursor(Convenience::flippedCursor(cursor));
d->_q_matchParentheses(); d->_q_matchParentheses();
return true; return true;
} }
...@@ -1346,7 +1338,7 @@ bool TextEditorWidget::selectBlockDown() ...@@ -1346,7 +1338,7 @@ bool TextEditorWidget::selectBlockDown()
if ( cursor != d->m_selectBlockAnchor) if ( cursor != d->m_selectBlockAnchor)
TextBlockUserData::findNextClosingParenthesis(&cursor, true); TextBlockUserData::findNextClosingParenthesis(&cursor, true);
setTextCursor(flippedCursor(cursor)); setTextCursor(Convenience::flippedCursor(cursor));
d->_q_matchParentheses(); d->_q_matchParentheses();
return true; return true;
} }
...@@ -5346,6 +5338,11 @@ const MarginSettings &TextEditorWidget::marginSettings() const ...@@ -5346,6 +5338,11 @@ const MarginSettings &TextEditorWidget::marginSettings() const
return d->m_marginSettings; return d->m_marginSettings;
} }
const BehaviorSettings &TextEditorWidget::behaviorSettings() const
{
return d->m_behaviorSettings;
}
void TextEditorWidgetPrivate::handleHomeKey(bool anchor) void TextEditorWidgetPrivate::handleHomeKey(bool anchor)
{ {
QTextCursor cursor = q->textCursor(); QTextCursor cursor = q->textCursor();
......
...@@ -294,6 +294,7 @@ public: ...@@ -294,6 +294,7 @@ public:
const DisplaySettings &displaySettings() const; const DisplaySettings &displaySettings() const;
const MarginSettings &marginSettings() const; const MarginSettings &marginSettings() const;
const BehaviorSettings &behaviorSettings() const;
void ensureCursorVisible(); void ensureCursorVisible();
...@@ -389,8 +390,8 @@ public: ...@@ -389,8 +390,8 @@ public:
void gotoNextWordCamelCase(); void gotoNextWordCamelCase();
void gotoNextWordCamelCaseWithSelection(); void gotoNextWordCamelCaseWithSelection();
bool selectBlockUp(); virtual bool selectBlockUp();
bool selectBlockDown(); virtual bool selectBlockDown();
void moveLineUp(); void moveLineUp();
void moveLineDown(); void moveLineDown();
...@@ -498,6 +499,7 @@ protected: ...@@ -498,6 +499,7 @@ protected:
void showDefaultContextMenu(QContextMenuEvent *e, Core::Id menuContextId); void showDefaultContextMenu(QContextMenuEvent *e, Core::Id menuContextId);
virtual void finalizeInitialization() {} virtual void finalizeInitialization() {}
virtual void finalizeInitializationAfterDuplication(TextEditorWidget *) {} virtual void finalizeInitializationAfterDuplication(TextEditorWidget *) {}
static QTextCursor flippedCursor(const QTextCursor &cursor);
public: public:
struct Link struct Link
......
...@@ -449,7 +449,7 @@ void TextEditorActionHandlerPrivate::createActions() ...@@ -449,7 +449,7 @@ void TextEditorActionHandlerPrivate::createActions()
G_EDIT_BLOCKS, advancedEditMenu); G_EDIT_BLOCKS, advancedEditMenu);
m_selectBlockDownAction = registerAction(SELECT_BLOCK_DOWN, m_selectBlockDownAction = registerAction(SELECT_BLOCK_DOWN,
[this] (TextEditorWidget *w) { w->selectBlockDown(); }, true, tr("Select Block Down"), [this] (TextEditorWidget *w) { w->selectBlockDown(); }, true, tr("Select Block Down"),
QKeySequence(), QKeySequence(tr("Ctrl+Shift+Alt+U")),
G_EDIT_BLOCKS, advancedEditMenu); G_EDIT_BLOCKS, advancedEditMenu);
// register GOTO Actions // register GOTO Actions
......
...@@ -11,6 +11,7 @@ SUBDIRS = \ ...@@ -11,6 +11,7 @@ SUBDIRS = \
typeprettyprinter \ typeprettyprinter \
misc \ misc \
c99 \ c99 \
cppselectionchanger\
cxx11 \ cxx11 \
checksymbols \ checksymbols \
lexer \ lexer \
......
...@@ -7,6 +7,7 @@ Project { ...@@ -7,6 +7,7 @@ Project {
"c99/c99.qbs", "c99/c99.qbs",
"checksymbols/checksymbols.qbs", "checksymbols/checksymbols.qbs",
"codeformatter/codeformatter.qbs", "codeformatter/codeformatter.qbs",
"cppselectionchanger/cppselectionchanger.qbs",
"cxx11/cxx11.qbs", "cxx11/cxx11.qbs",
"fileiterationorder/fileiterationorder.qbs", "fileiterationorder/fileiterationorder.qbs",
"findusages/findusages.qbs", "findusages/findusages.qbs",
......
include(../shared/shared.pri)
# Inject the source dir for referencing test data from shadow builds.
DEFINES += SRCDIR=\\\"$$PWD\\\"
SOURCES += tst_cppselectionchangertest.cpp
DISTFILES += testCppFile.cpp \
cppselectionchanger.qbs
import qbs
import "../cplusplusautotest.qbs" as CPlusPlusAutotest
CPlusPlusAutotest {
name: "CPlusPlus selection changer autotest"
Group {
name: "Source Files"
files: "tst_cppselectionchangertest.cpp"
}
Group {
name: "Data Files"
fileTags: ["data"]
files: [
"testCppFile.cpp",
]
}
cpp.defines: base.concat(['SRCDIR="' + path + '"'])
}
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include <string>
#include <iostream>
#include <map>
#include <vector>
struct TestClass {
int a;
char b;
char x;
char y;
char z;
std::string c;
double d;
std::map<int, int> e;
};
int add(int a, int b) {
return a + b;
}
template <class T>
int subtract(T a, T b) {
return a - b;
}
namespace CustomNamespace {
extern int insideNamespace;
int foo() {
insideNamespace = 2;
return insideNamespace;
}
}
class CustomClass {
bool customClassMethod(const int &parameter) const volatile;
};
class SecondCustomClass {