Commit e9ad023d authored by mae's avatar mae

block navigation and selection (bound to Ctrl+[]{}

parent 9e51c725
......@@ -162,7 +162,10 @@ int BaseTextFind::replaceAll(const QString &before, const QString &after,
QTextDocument::FindFlags findFlags)
{
QTextCursor editCursor = textCursor();
editCursor.movePosition(QTextCursor::Start);
if (!m_findScope.isNull())
editCursor.setPosition(m_findScope.selectionStart());
else
editCursor.movePosition(QTextCursor::Start);
editCursor.beginEditBlock();
int count = 0;
QTextCursor found;
......
......@@ -531,7 +531,6 @@ void BaseTextEditor::selectEncoding()
}
}
void DocumentMarker::updateMark(ITextMark *mark)
{
TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(document->documentLayout());
......@@ -600,6 +599,36 @@ void BaseTextEditor::slotSelectionChanged()
d->m_blockSelectionExtraX = 0;
}
void BaseTextEditor::gotoBlockStart()
{
QTextCursor cursor = textCursor();
if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, false))
setTextCursor(cursor);
}
void BaseTextEditor::gotoBlockEnd()
{
QTextCursor cursor = textCursor();
if (TextBlockUserData::findNextClosingParenthesis(&cursor, false))
setTextCursor(cursor);
}
void BaseTextEditor::gotoBlockStartWithSelection()
{
QTextCursor cursor = textCursor();
if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, true))
setTextCursor(cursor);
}
void BaseTextEditor::gotoBlockEndWithSelection()
{
QTextCursor cursor = textCursor();
if (TextBlockUserData::findNextClosingParenthesis(&cursor, true))
setTextCursor(cursor);
}
void BaseTextEditor::keyPressEvent(QKeyEvent *e)
{
......@@ -633,6 +662,11 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
e->accept();
return;
}
} else if (e == QKeySequence::Paste) {
if (!ro) {
d->removeBlockSelection();
// continue
}
}
}
......@@ -693,6 +727,8 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
break;
case Qt::Key_Home:
if (!(e == QKeySequence::MoveToStartOfDocument) && !(e == QKeySequence::SelectStartOfDocument)) {
if ((e->modifiers() & (Qt::AltModifier | Qt::ShiftModifier)) == (Qt::AltModifier | Qt::ShiftModifier))
d->m_lastEventWasBlockSelectionEvent = true;
handleHomeKey(e->modifiers() & Qt::ShiftModifier);
e->accept();
return;
......@@ -708,6 +744,7 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
return;
}
// fall through
case Qt::Key_End:
case Qt::Key_Right:
case Qt::Key_Left:
#ifndef Q_OS_MAC
......@@ -795,6 +832,15 @@ skip_event:
delete e;
}
void BaseTextEditor::setTextCursor(const QTextCursor &cursor)
{
// workaround for QTextControl bug
bool selectionChange = cursor.hasSelection() || textCursor().hasSelection();
QPlainTextEdit::setTextCursor(cursor);
if (selectionChange)
slotSelectionChanged();
}
void BaseTextEditor::gotoLine(int line, int column)
{
const int blockNumber = line - 1;
......@@ -2908,6 +2954,61 @@ TextBlockUserData::MatchType TextBlockUserData::checkClosedParenthesis(QTextCurs
}
}
bool TextBlockUserData::findPreviousOpenParenthesis(QTextCursor *cursor, bool select)
{
QTextBlock block = cursor->block();
int position = cursor->position();
int ignore = 0;
while (block.isValid()) {
Parentheses parenList = TextEditDocumentLayout::parentheses(block);
if (!parenList.isEmpty()) {
for (int i = parenList.count()-1; i >= 0; --i) {
Parenthesis paren = parenList.at(i);
if (block == cursor->block() && position - block.position() <= paren.pos + 1)
continue;
if (paren.type == Parenthesis::Closed) {
++ignore;
} else if (ignore > 0) {
--ignore;
} else {
cursor->setPosition(block.position() + paren.pos, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor);
return true;
}
}
}
block = block.previous();
}
return false;
}
bool TextBlockUserData::findNextClosingParenthesis(QTextCursor *cursor, bool select)
{
QTextBlock block = cursor->block();
int position = cursor->position();
int ignore = 0;
while (block.isValid()) {
Parentheses parenList = TextEditDocumentLayout::parentheses(block);
if (!parenList.isEmpty()) {
for (int i = 0; i < parenList.count(); ++i) {
Parenthesis paren = parenList.at(i);
if (block == cursor->block() && position - block.position() >= paren.pos)
continue;
if (paren.type == Parenthesis::Opened) {
++ignore;
} else if (ignore > 0) {
--ignore;
} else {
cursor->setPosition(block.position() + paren.pos+1, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor);
return true;
}
}
}
block = block.next();
}
return false;
}
TextBlockUserData::MatchType TextBlockUserData::matchCursorBackward(QTextCursor *cursor)
{
cursor->clearSelection();
......@@ -3152,13 +3253,16 @@ void BaseTextEditor::collapse()
TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout());
Q_ASSERT(documentLayout);
QTextBlock block = textCursor().block();
qDebug() << "collapse at block" << block.blockNumber();
while (block.isValid()) {
if (TextBlockUserData::canCollapse(block)) {
if ((block.next().userState()) >> 8 == (textCursor().block().userState() >> 8))
qDebug() << "test block" << block.blockNumber();
if (TextBlockUserData::canCollapse(block) && block.next().isVisible()) {
if ((block.next().userState()) >> 8 <= (textCursor().block().userState() >> 8))
break;
}
block = block.previous();
}
qDebug() << "found" << block.blockNumber();
if (block.isValid()) {
TextBlockUserData::doCollapse(block, false);
d->moveCursorVisible();
......@@ -3238,6 +3342,14 @@ void BaseTextEditor::cut()
QPlainTextEdit::cut();
}
void BaseTextEditor::paste()
{
if (d->m_inBlockSelectionMode) {
d->removeBlockSelection();
}
QPlainTextEdit::paste();
}
QMimeData *BaseTextEditor::createMimeDataFromSelection() const
{
if (d->m_inBlockSelectionMode) {
......
......@@ -169,6 +169,8 @@ public:
static MatchType checkClosedParenthesis(QTextCursor *cursor, QChar c);
static MatchType matchCursorBackward(QTextCursor *cursor);
static MatchType matchCursorForward(QTextCursor *cursor);
static bool findPreviousOpenParenthesis(QTextCursor *cursor, bool select = false);
static bool findNextClosingParenthesis(QTextCursor *cursor, bool select = false);
private:
......@@ -298,6 +300,8 @@ public:
void setReadOnly(bool b);
void setTextCursor(const QTextCursor &cursor);
public slots:
void setDisplayName(const QString &title);
virtual void setFontSettings(const TextEditor::FontSettings &);
......@@ -305,6 +309,7 @@ public slots:
virtual void unCommentSelection();
virtual void setStorageSettings(const TextEditor::StorageSettings &);
void paste();
void cut();
void zoomIn(int range = 1);
......@@ -316,6 +321,11 @@ public slots:
void expand();
void selectEncoding();
void gotoBlockStart();
void gotoBlockEnd();
void gotoBlockStartWithSelection();
void gotoBlockEndWithSelection();
signals:
void changed();
......
......@@ -67,6 +67,8 @@ TextEditorActionHandler::TextEditorActionHandler(Core::ICore *core,
= m_collapseAction = m_expandAction
= m_deleteLineAction = m_selectEncodingAction
= m_increaseFontSizeAction = m_decreaseFontSizeAction
= m_gotoBlockStartAction = m_gotoBlockStartWithSelectionAction
= m_gotoBlockEndAction = m_gotoBlockEndWithSelectionAction
= 0;
m_contextId << m_core->uniqueIDManager()->uniqueIdentifier(context);
......@@ -185,6 +187,27 @@ void TextEditorActionHandler::createActions()
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+-")));
connect(m_decreaseFontSizeAction, SIGNAL(triggered()), this, SLOT(decreaseFontSize()));
advancedMenu->addAction(command);
m_gotoBlockStartAction = new QAction(tr("Goto Block Start"), this);
command = am->registerAction(m_gotoBlockStartAction, Constants::GOTO_BLOCK_START, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+[")));
connect(m_gotoBlockStartAction, SIGNAL(triggered()), this, SLOT(gotoBlockStart()));
m_gotoBlockEndAction = new QAction(tr("Goto Block End"), this);
command = am->registerAction(m_gotoBlockEndAction, Constants::GOTO_BLOCK_END, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+]")));
connect(m_gotoBlockEndAction, SIGNAL(triggered()), this, SLOT(gotoBlockEnd()));
m_gotoBlockStartWithSelectionAction = new QAction(tr("Goto Block Start With Selection"), this);
command = am->registerAction(m_gotoBlockStartWithSelectionAction, Constants::GOTO_BLOCK_START_WITH_SELECTION, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+{")));
connect(m_gotoBlockStartWithSelectionAction, SIGNAL(triggered()), this, SLOT(gotoBlockStartWithSelection()));
m_gotoBlockEndWithSelectionAction = new QAction(tr("Goto Block End With Selection"), this);
command = am->registerAction(m_gotoBlockEndWithSelectionAction, Constants::GOTO_BLOCK_END_WITH_SELECTION, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+}")));
connect(m_gotoBlockEndWithSelectionAction, SIGNAL(triggered()), this, SLOT(gotoBlockEndWithSelection()));
}
bool TextEditorActionHandler::supportsAction(const QString & /*id */) const
......@@ -365,54 +388,29 @@ void TextEditorActionHandler::setTextWrapping(bool checked)
}
}
void TextEditorActionHandler::unCommentSelection()
{
if (m_currentEditor)
m_currentEditor->unCommentSelection();
}
void TextEditorActionHandler::deleteLine()
{
if (m_currentEditor)
m_currentEditor->deleteLine();
}
void TextEditorActionHandler::unCollapseAll()
{
if (m_currentEditor)
m_currentEditor->unCollapseAll();
}
void TextEditorActionHandler::collapse()
{
if (m_currentEditor)
m_currentEditor->collapse();
}
void TextEditorActionHandler::expand()
{
if (m_currentEditor)
m_currentEditor->expand();
}
void TextEditorActionHandler::selectEncoding()
{
if (m_currentEditor)
m_currentEditor->selectEncoding();
}
void TextEditorActionHandler::increaseFontSize()
{
if (m_currentEditor)
m_currentEditor->zoomIn();
}
void TextEditorActionHandler::decreaseFontSize()
{
if (m_currentEditor)
m_currentEditor->zoomOut();
}
#define FUNCTION(funcname) void TextEditorActionHandler::funcname ()\
{\
if (m_currentEditor)\
m_currentEditor->funcname ();\
}
#define FUNCTION2(funcname, funcname2) void TextEditorActionHandler::funcname ()\
{\
if (m_currentEditor)\
m_currentEditor->funcname2 ();\
}
FUNCTION(unCommentSelection)
FUNCTION(deleteLine)
FUNCTION(unCollapseAll)
FUNCTION(collapse)
FUNCTION(expand)
FUNCTION2(increaseFontSize, zoomIn)
FUNCTION2(decreaseFontSize, zoomOut)
FUNCTION(selectEncoding)
FUNCTION(gotoBlockStart)
FUNCTION(gotoBlockEnd)
FUNCTION(gotoBlockStartWithSelection)
FUNCTION(gotoBlockEndWithSelection)
void TextEditorActionHandler::updateCurrentEditor(Core::IContext *object)
{
......
......@@ -109,6 +109,10 @@ private slots:
void selectEncoding();
void increaseFontSize();
void decreaseFontSize();
void gotoBlockStart();
void gotoBlockEnd();
void gotoBlockStartWithSelection();
void gotoBlockEndWithSelection();
void updateCurrentEditor(Core::IContext *object);
private:
......@@ -131,6 +135,10 @@ private:
QAction *m_selectEncodingAction;
QAction *m_increaseFontSizeAction;
QAction *m_decreaseFontSizeAction;
QAction *m_gotoBlockStartAction;
QAction *m_gotoBlockEndAction;
QAction *m_gotoBlockStartWithSelectionAction;
QAction *m_gotoBlockEndWithSelectionAction;
uint m_optionalActions;
QPointer<BaseTextEditor> m_currentEditor;
......
......@@ -48,9 +48,15 @@ const char * const UN_COLLAPSE_ALL = "TextEditor.UnCollapseAll";
const char * const AUTO_INDENT_SELECTION = "TextEditor.AutoIndentSelection";
const char * const INCREASE_FONT_SIZE = "TextEditor.IncreaseFontSize";
const char * const DECREASE_FONT_SIZE = "TextEditor.DecreaseFontSize";
const char * const GOTO_BLOCK_START = "TextEditor.GotoBlockStart";
const char * const GOTO_BLOCK_START_WITH_SELECTION = "TextEditor.GotoBlockStartWithSelection";
const char * const GOTO_BLOCK_END = "TextEditor.GotoBlockEnd";
const char * const GOTO_BLOCK_END_WITH_SELECTION = "TextEditor.GotoBlockEndWithSelection";
const char * const DELETE_LINE = "TextEditor.DeleteLine";
const char * const DELETE_WORD = "TextEditor.DeleteWord";
const char * const SELECT_ENCODING = "TextEditor.SelectEncoding";
const char * const GOTO_OPENING_PARENTHESIS = "TextEditor.GotoOpeningParenthesis";
const char * const GOTO_CLOSING_PARENTHESIS = "TextEditor.GotoOpeningParenthesis";
const char * const C_TEXTEDITOR_MIMETYPE_TEXT = "text/plain";
const char * const C_TEXTEDITOR_MIMETYPE_XML = "application/xml";
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment