forked from qt-creator/qt-creator
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: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
committed by
Nikolai Kosjar
parent
8bfdc82c5a
commit
bed88818ce
@@ -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 @@
|
|||||||
#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:
|
|||||||
|
|
||||||
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)
|
|||||||
, 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()
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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:
|
|||||||
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;
|
||||||
|
|||||||
1113
src/plugins/cpptools/cppselectionchanger.cpp
Normal file
1113
src/plugins/cpptools/cppselectionchanger.cpp
Normal file
File diff suppressed because it is too large
Load Diff
128
src/plugins/cpptools/cppselectionchanger.h
Normal file
128
src/plugins/cpptools/cppselectionchanger.h
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 += \
|
|||||||
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 += \
|
|||||||
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 {
|
|||||||
"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";
|
|||||||
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() :
|
|||||||
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
|
|||||||
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)
|
|||||||
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
|
|||||||
&& 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:
|
|||||||
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)
|
|||||||
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
|
|||||||
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
|
|||||||
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.
|
|||||||
</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)
|
|||||||
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,
|
|||||||
|
|
||||||
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()
|
|||||||
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()
|
|||||||
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()
|
|||||||
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
|
|||||||
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:
|
|||||||
|
|
||||||
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:
|
|||||||
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:
|
|||||||
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()
|
|||||||
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 = \
|
|||||||
typeprettyprinter \
|
typeprettyprinter \
|
||||||
misc \
|
misc \
|
||||||
c99 \
|
c99 \
|
||||||
|
cppselectionchanger\
|
||||||
cxx11 \
|
cxx11 \
|
||||||
checksymbols \
|
checksymbols \
|
||||||
lexer \
|
lexer \
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
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 + '"'])
|
||||||
|
}
|
||||||
124
tests/auto/cplusplus/cppselectionchanger/testCppFile.cpp
Normal file
124
tests/auto/cplusplus/cppselectionchanger/testCppFile.cpp
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 ¶meter) const volatile;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SecondCustomClass {
|
||||||
|
public:
|
||||||
|
SecondCustomClass(int argc, char *argv[]);
|
||||||
|
void secondCustomClassFunction();
|
||||||
|
};
|
||||||
|
|
||||||
|
bool CustomClass::customClassMethod(const int ¶meter) const volatile {
|
||||||
|
int secondParameter = parameter;
|
||||||
|
++secondParameter;
|
||||||
|
return secondParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
std::map<int,TestClass> a;
|
||||||
|
|
||||||
|
SecondCustomClass secondCustomClass(argc, argv);
|
||||||
|
secondCustomClass.secondCustomClassFunction();
|
||||||
|
|
||||||
|
TestClass bla;
|
||||||
|
bla.a = 1;
|
||||||
|
bla.b = 65;
|
||||||
|
bla.c = "Hello";
|
||||||
|
bla.d = 3.14f;
|
||||||
|
bla.e[3] = 3;
|
||||||
|
|
||||||
|
a[3] = bla;
|
||||||
|
|
||||||
|
std::vector<int> v;
|
||||||
|
v.push_back(1);
|
||||||
|
v.push_back(2);
|
||||||
|
|
||||||
|
if (5 == 5) {
|
||||||
|
std::cout << "Hello" << 'c' << 54545 << u8"utf8string" << U"unicodeString";
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
std::cout << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto val :v) {
|
||||||
|
std::cout << val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\n After exec";
|
||||||
|
std::cout << argc << argv;
|
||||||
|
|
||||||
|
std::cout << add(1, add(2, add(10, 20)));
|
||||||
|
|
||||||
|
auto res = std::find(v.begin(), v.end(), 1);
|
||||||
|
if (res != v.end())
|
||||||
|
std::cout << *res;
|
||||||
|
std::cout << static_cast<int>(3);
|
||||||
|
|
||||||
|
auto aLambda = [=, &a](int lambdaArgument) -> int {
|
||||||
|
return lambdaArgument + 1;
|
||||||
|
};
|
||||||
|
aLambda(1);
|
||||||
|
|
||||||
|
std::cout << R"(
|
||||||
|
Raw literal
|
||||||
|
)";
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user