diff --git a/src/include/ktexteditor/view.h b/src/include/ktexteditor/view.h --- a/src/include/ktexteditor/view.h +++ b/src/include/ktexteditor/view.h @@ -648,6 +648,7 @@ * KF6: Remove, Block selection is no longer a state. */ virtual bool blockSelection() const = 0; + virtual bool blockSelection2() const = 0; /* * SIGNALS diff --git a/src/view/katemulticursor.cpp b/src/view/katemulticursor.cpp --- a/src/view/katemulticursor.cpp +++ b/src/view/katemulticursor.cpp @@ -95,12 +95,20 @@ void makeValid() { m_cursor.setLine(qBound(0, line(), int(doc()->lines() - 1))); + + // Ignore issues past the end of the line when in block mode (v2) + if (view()->blockSelection2() && column() >= 0) { + return; + } + if (view()->wrapCursor()) { m_cursor.setColumn(qBound(0, column(), doc()->lineLength(line()))); } else { m_cursor.setColumn(qMax(0, column())); } - Q_ASSERT(valid()); + + //ELV13 TODO check if ctrl+meta+f is set then ignore !valid() && >0 + //Q_ASSERT(valid()); } void toEdge(KateViewInternal::Bias bias) @@ -176,7 +184,7 @@ int maxColumn = -1; if (n >= 0) { for (int i = 0; i < n; i++) { - if (column() >= thisLine->length()) { + if (column() >= thisLine->length() && !view()->blockSelection2()) { if (wrapCursor) { break; @@ -198,7 +206,12 @@ } } else { - m_cursor.setColumn(thisLine->layout()->nextCursorPosition(column())); + + if ((!view()->blockSelection2()) && column() >= 0 && thisLine->layout()->isValidCursorPosition(column()) + 1) { + m_cursor.setColumn(thisLine->layout()->nextCursorPosition(column())); + } else { + m_cursor.setColumn(column() + 1); + } } } } else { @@ -213,7 +226,8 @@ } } - Q_ASSERT(valid()); + //ELV13 no longer true + //Q_ASSERT(valid()); return *this; } CalculatingCursor &operator-=(int n) Q_DECL_OVERRIDE @@ -514,6 +528,25 @@ { qDebug() << "called" << sel << chars; CursorRepainter rep(this); + + // When there is no selection and the block mode is active, add more cursors + if (sel && (!selections()->hasMultipleSelections()) && (!selections()->hasSelections())) { + // Find the best place to add a new cursor + int minRow = std::numeric_limits::max(), col(-1); + + Q_FOREACH (const auto& cursor, allCursors()) { + if ((minRow = qMin(cursor.data()->line(), minRow)) == cursor.data()->line()) { + col = cursor.data()->column(); + } + } + + if (minRow != std::numeric_limits::max() && col >= 0) { + toggleSecondaryCursorAt(BoundedCursor(viewInternal(), minRow -1, col)); + return; + } + + } + KateMultiSelection::SelectingCursorMovement mov(selections(), sel); for ( int i = 0; i < abs(chars); i++ ) { Q_FOREACH (const auto& cursor, allCursors()) { @@ -532,6 +565,25 @@ void KateMultiCursor::moveCursorsDown(bool sel, int32_t chars) { qDebug() << "called" << sel << chars; + + // When there is no selection and the block mode is active, add more cursors + if (sel && (!selections()->hasMultipleSelections()) && (!selections()->hasSelections())) { + // Find the best place to add a new cursor + int maxRow = 0, col(-1); + + Q_FOREACH (const auto& cursor, allCursors()) { + if ((maxRow = qMin(cursor.data()->line(), maxRow)) == cursor.data()->line()) { + col = cursor.data()->column(); + } + } + + if (maxRow != view()->document()->lines() - 1 && col >= 0) { + toggleSecondaryCursorAt(BoundedCursor(viewInternal(), maxRow + 1, col)); + return; + } + + } + moveCursorsUp(sel, -chars); } @@ -667,7 +719,12 @@ Cursor KateMultiCursor::moveLeftRight(const Cursor& start, int32_t chars) const { KTextEditor::Cursor c; - if (view()->wrapCursor()) { + + const bool isBlockV2 = view()->blockSelection2() + && (!selections()->hasMultipleSelections()) + && (!selections()->hasSelections()); + + if (view()->wrapCursor() && !isBlockV2) { c = WrappingCursor(viewInternal(), start) += chars; } else { c = BoundedCursor(viewInternal(), start) += chars; diff --git a/src/view/kateview.h b/src/view/kateview.h --- a/src/view/kateview.h +++ b/src/view/kateview.h @@ -304,6 +304,7 @@ bool setBlockSelection(bool on) override; bool toggleBlockSelection(); bool toAlignedBlock(bool fill); + bool blockSelection2() const override; bool clearSelection(); bool clearSelection(bool redraw, bool finishedChangingSelection = true); @@ -697,6 +698,7 @@ QActionGroup *m_inputModeActions; KToggleAction *m_toggleBlockSelection; + KToggleAction *m_toggleToAlignedBlock; KToggleAction *m_toggleInsert; KToggleAction *m_toggleWriteLock; diff --git a/src/view/kateview.cpp b/src/view/kateview.cpp --- a/src/view/kateview.cpp +++ b/src/view/kateview.cpp @@ -670,7 +670,8 @@ a->setWhatsThis(i18n("This command allows switching an existing selection between a block of text and a continuous (line-based) selection.")); connect(a, SIGNAL(triggered(bool)), SLOT(toggleBlockSelection())); - a = ac->addAction(QStringLiteral("selection_to_block"), this); + a = m_toggleToAlignedBlock = new KToggleAction(QStringLiteral("selection_to_block"), this); + ac->addAction(QStringLiteral("set_verticalSelect2"), a); a->setText(i18n("Selection to aligned block")); ac->setDefaultShortcut(a, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_B)); a->setWhatsThis(i18n("Transforms a selection to an aligned selection block, filling up lines with space characters as needed.")); @@ -2288,6 +2289,11 @@ return false; } +bool KTextEditor::ViewPrivate::blockSelection2() const +{ + return m_toggleToAlignedBlock->isChecked(); +} + bool KTextEditor::ViewPrivate::setBlockSelection(bool /*on*/) { return toAlignedBlock(false);