Treat links as a single character for the purposes of delete, backspace, left and right.
When backspacing at a link the first key selects the whole link the second deletes. Similar for delete, left and right.
This commit is contained in:
@@ -22,6 +22,10 @@ bool ChatKeyHelper::handleKey(Qt::Key key, Qt::KeyboardModifiers modifiers)
|
|||||||
return up(modifiers);
|
return up(modifiers);
|
||||||
case Qt::Key_Down:
|
case Qt::Key_Down:
|
||||||
return down();
|
return down();
|
||||||
|
case Qt::Key_Left:
|
||||||
|
return left();
|
||||||
|
case Qt::Key_Right:
|
||||||
|
return right();
|
||||||
case Qt::Key_Tab:
|
case Qt::Key_Tab:
|
||||||
return tab();
|
return tab();
|
||||||
case Qt::Key_Delete:
|
case Qt::Key_Delete:
|
||||||
@@ -104,6 +108,30 @@ bool ChatKeyHelper::down()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChatKeyHelper::left()
|
||||||
|
{
|
||||||
|
if (!textItem) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QTextCursor cursor = textItem->textCursor();
|
||||||
|
if (cursor.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return selectLink(cursor, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatKeyHelper::right()
|
||||||
|
{
|
||||||
|
if (!textItem) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QTextCursor cursor = textItem->textCursor();
|
||||||
|
if (cursor.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return selectLink(cursor, false);
|
||||||
|
}
|
||||||
|
|
||||||
bool ChatKeyHelper::tab()
|
bool ChatKeyHelper::tab()
|
||||||
{
|
{
|
||||||
if (!textItem) {
|
if (!textItem) {
|
||||||
@@ -139,7 +167,7 @@ bool ChatKeyHelper::deleteChar()
|
|||||||
Q_EMIT unhandledDelete();
|
Q_EMIT unhandledDelete();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return selectLink(cursor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatKeyHelper::backspace()
|
bool ChatKeyHelper::backspace()
|
||||||
@@ -160,7 +188,7 @@ bool ChatKeyHelper::backspace()
|
|||||||
Q_EMIT unhandledBackspace();
|
Q_EMIT unhandledBackspace();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return selectLink(cursor, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatKeyHelper::insertReturn(Qt::KeyboardModifiers modifiers)
|
bool ChatKeyHelper::insertReturn(Qt::KeyboardModifiers modifiers)
|
||||||
@@ -227,4 +255,60 @@ bool ChatKeyHelper::pasteImage()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChatKeyHelper::selectLink(QTextCursor &cursor, bool back)
|
||||||
|
{
|
||||||
|
if (cursor.hasSelection() || (!cursor.charFormat().isAnchor() && back) || (!back && cursor.atBlockEnd())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are on the very right and going right we need to exit.
|
||||||
|
if (!back) {
|
||||||
|
const auto startPos = cursor.position();
|
||||||
|
cursor.movePosition(QTextCursor::NextCharacter);
|
||||||
|
if (cursor.charFormat().isAnchor()) {
|
||||||
|
cursor.setPosition(startPos);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out if we're on the left side of a link.
|
||||||
|
// note a cusor on the leftmost of a link will not have the anchor set in char format.
|
||||||
|
bool onLeft = false;
|
||||||
|
if (!cursor.charFormat().isAnchor() && !back) {
|
||||||
|
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
|
||||||
|
if (cursor.charFormat().isAnchor()) {
|
||||||
|
onLeft = true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto hRef = cursor.charFormat().anchorHref();
|
||||||
|
auto currentCharFormat = cursor.charFormat();
|
||||||
|
|
||||||
|
// If not on the left figure out where it is.
|
||||||
|
if (!onLeft) {
|
||||||
|
const auto startPos = cursor.position();
|
||||||
|
while (currentCharFormat.isAnchor() && currentCharFormat.anchorHref() == hRef && cursor.position() > 0) {
|
||||||
|
cursor.movePosition(QTextCursor::PreviousCharacter);
|
||||||
|
currentCharFormat = cursor.charFormat();
|
||||||
|
}
|
||||||
|
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, startPos - cursor.position());
|
||||||
|
}
|
||||||
|
// Then select everything to right.
|
||||||
|
// We do it this way so it works when you start in the middle.
|
||||||
|
currentCharFormat = cursor.charFormat();
|
||||||
|
while (currentCharFormat.isAnchor() && currentCharFormat.anchorHref() == hRef && cursor.position() < cursor.block().length() - 1) {
|
||||||
|
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
|
||||||
|
currentCharFormat = cursor.charFormat();
|
||||||
|
}
|
||||||
|
if (!currentCharFormat.isAnchor()) {
|
||||||
|
cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
textItem->setSelection(cursor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_chatkeyhelper.cpp"
|
#include "moc_chatkeyhelper.cpp"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
class QTextCursor;
|
||||||
|
|
||||||
class ChatTextItemHelper;
|
class ChatTextItemHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,6 +121,10 @@ private:
|
|||||||
|
|
||||||
bool down();
|
bool down();
|
||||||
|
|
||||||
|
bool left();
|
||||||
|
|
||||||
|
bool right();
|
||||||
|
|
||||||
bool tab();
|
bool tab();
|
||||||
|
|
||||||
bool deleteChar();
|
bool deleteChar();
|
||||||
@@ -130,4 +136,6 @@ private:
|
|||||||
bool cancel();
|
bool cancel();
|
||||||
|
|
||||||
bool pasteImage();
|
bool pasteImage();
|
||||||
|
|
||||||
|
bool selectLink(QTextCursor &cursor, bool back);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -387,6 +387,14 @@ void ChatTextItemHelper::setCursorPosition(int pos)
|
|||||||
m_textItem->setProperty("cursorPosition", pos);
|
m_textItem->setProperty("cursorPosition", pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatTextItemHelper::setSelection(const QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
if (!m_textItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
metaObject()->invokeMethod(m_textItem, "select", Qt::DirectConnection, cursor.selectionStart(), cursor.selectionEnd());
|
||||||
|
}
|
||||||
|
|
||||||
void ChatTextItemHelper::setCursorVisible(bool visible)
|
void ChatTextItemHelper::setCursorVisible(bool visible)
|
||||||
{
|
{
|
||||||
if (!m_textItem) {
|
if (!m_textItem) {
|
||||||
|
|||||||
@@ -187,6 +187,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setCursorPosition(int pos);
|
void setCursorPosition(int pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the selection of the underlying text item to the given cursor.
|
||||||
|
*/
|
||||||
|
void setSelection(const QTextCursor &cursor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the cursor visibility of the underlying text item to the given value.
|
* @brief Set the cursor visibility of the underlying text item to the given value.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user