Qt: Как текстовые редакторы выполняют операцию замены и останавливаются, когда возвращаются к первой замене, которую они когда-либо выполняли? - PullRequest
0 голосов
/ 09 января 2019

Я работаю над проектом текстового редактора в Qt, и в настоящее время я пытаюсь имитировать поведение текстовых редакторов и текстовых редакторов "Найти и заменить".

Рассмотрим этот пример из Microsoft Word, с цифрами, указывающими позицию / индекс курсора в конце каждой строки:

привет 5

Мэйти 11

привет 17

Другими словами, если курсор находится в самом начале документа (слева от «привет»), его индекс будет равен 0. Справа от первого «h» он будет равен 1. И скоро. Вот как Qt обрабатывает позиции курсора в пределах QTextEdit (или, в данном случае, QPlainTextEdit).

Предположим, что наш курсор в данный момент расположен сразу после «matey», в позиции 11, и что мы открыли диалог поиска (с помощью Ctrl + F или действия меню).

В текстовом редакторе, таком как Microsoft Word, поиск «hello» будет продолжаться, чтобы найти нижнее «hello» в позиции 17, затем вернуться к началу и найти первое «hello» в позиции 5, а затем остановить поиск, как только он возвращается к позиции, где он нашел свое первое совпадение (17). Это имеет смысл - вам не захочется постоянно повторять пользователя по всему документу и создавать впечатление, что вы находите «новые» попадания, хотя на самом деле это не так.

Более того, когда вы выходите из поиска, ваш курсор вернется в свою исходную позицию перед первым поиском, который вы провели для рассматриваемого термина (то есть курсор вернется в позицию 11 и не останется в позиции 17, «ложная положительная» новая находка).

Такое поведение ожидается и работает как задумано в моем собственном текстовом редакторе. Соответствующие части кода для проверки следующие:

Позвольте мне объяснить мой собственный подход, прежде чем описывать проблему более подробно:

Класс FindDialog хранит карту, связывающую каждый поисковый запрос / термин с парой позиций / целых чисел: первое целое число - это позиция, в которой находился курсор до первого поиска по этому термину (в нашем примере, 11) ; второе целое число в паре - это позиция, в которой было найдено первое совпадение (в нашем примере это будет 17).

Поиск продолжается до конца документа. Если совпадение не найдено, выполняется другой поиск с начала документа. Если мы окажемся в позиции , равной первому совпадению , мы будем рассматривать ее как «ошибку поиска», сбрасываем нашу историю поиска и возвращаемся.

Теперь перейдем к операции «Заменить», которая сначала вызывает операцию «Найти», а затем вставляет текст замены в курсор, расположенный с помощью операции «Найти». Смотрите эту строку .

Вот проблема: с операцией Replace предположим, что мы ищем «hello» и пытаемся заменить его на «hellos». Сначала мы заменим нижнюю часть "привет" на "привет". Все идет нормально. Затем мы заменим верхнюю часть "привет" на "привет". И затем мы возвращаемся к основанию «привет». Но вот проблема: наш курсор больше не находится в позиции 17, потому что вставка «hellos» в верхней части документа просто сместила все индексы / позиции курсора вверх на 1. То есть, индекс справа от нижний «привет» будет 18, а не 17. Вот некоторый код отладки, который подтверждает это поведение:

enter image description here

Причина, по которой я упоминаю об этом, заключается в том, что есть обходной путь, который я мог бы использовать, когда я устанавливаю какой-то флаг в редакторе - canReplace - который проверяется перед заменой содержимого. Этот флаг будет установлен в false, когда мы вернемся к первому совпадению Find. Конечно, когда я это проверял, это не работает из-за смещения позиций курсора, как я описал выше.

Есть ли более чистое или лучшее решение, о котором я просто не думаю? Я знаю, что это был действительно длинный пост, но я был бы признателен за любую помощь. Спасибо тем, кто все это прочитал :) 1071 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...