@@ -8,9 +8,8 @@ SearchableTextEdit::SearchableTextEdit(QWidget *parent) : QPlainTextEdit(parent)
88
99QPair<int , int > SearchableTextEdit::search (const QString &string, int options)
1010{
11- m_searchCursors .clear ();
11+ m_searchResults .clear ();
1212 m_currentIndex = -1 ;
13- m_searchedMatchLen = -1 ;
1413 m_highlightMatches = options & SearchOption::HighlightMatches;
1514
1615 if (string.isEmpty ()) {
@@ -34,7 +33,12 @@ QPair<int, int> SearchableTextEdit::search(const QString &string, int options)
3433 const QRegularExpression regex (string);
3534 while (!cursor.isNull () && !cursor.atEnd ()) {
3635 cursor = doc->find (regex, cursor, flags);
37- handleMatch (cursor, originalCursor);
36+
37+ if (cursor.hasSelection ()) {
38+ handleMatch (cursor, originalCursor);
39+ } else {
40+ cursor.movePosition (QTextCursor::NextCharacter); // avoid infinite loop
41+ }
3842 }
3943 } else {
4044 while (!cursor.isNull () && !cursor.atEnd ()) {
@@ -44,14 +48,14 @@ QPair<int, int> SearchableTextEdit::search(const QString &string, int options)
4448 }
4549
4650 // wrap around
47- if (m_currentIndex < 0 && !m_searchCursors .isEmpty ()) {
51+ if (m_currentIndex < 0 && !m_searchResults .isEmpty ()) {
4852 m_currentIndex = 0 ;
4953 }
5054
5155 scrollToCurrentIndex ();
5256 highlightMatches ();
5357
54- return { m_currentIndex, m_searchCursors .size () };
58+ return { m_currentIndex, m_searchResults .size () };
5559}
5660
5761void SearchableTextEdit::handleMatch (const QTextCursor ¤tCursor,
@@ -60,22 +64,27 @@ void SearchableTextEdit::handleMatch(const QTextCursor ¤tCursor,
6064 if (!currentCursor.isNull ()) {
6165
6266 if (m_currentIndex < 0 && currentCursor.selectionEnd () >= originalCursor.selectionStart ()) {
63- m_currentIndex = m_searchCursors .size ();
67+ m_currentIndex = m_searchResults .size ();
6468 }
6569
66- m_searchCursors.append (currentCursor);
70+ int len = currentCursor.selectionEnd () - currentCursor.selectionStart ();
71+ m_searchResults.append (SearchResult { currentCursor.selectionStart (), len });
6772 }
6873}
6974
7075void SearchableTextEdit::clearSearch ()
7176{
7277 this ->setExtraSelections ({});
73- m_searchCursors .clear ();
78+ m_searchResults .clear ();
7479}
7580
7681int SearchableTextEdit::findNext ()
7782{
78- m_currentIndex = (m_currentIndex + 1 ) % m_searchCursors.size ();
83+ if (m_searchResults.isEmpty ()) {
84+ return 0 ;
85+ }
86+
87+ m_currentIndex = (m_currentIndex + 1 ) % m_searchResults.size ();
7988
8089 scrollToCurrentIndex ();
8190 highlightMatches ();
@@ -85,7 +94,11 @@ int SearchableTextEdit::findNext()
8594
8695int SearchableTextEdit::findPrev ()
8796{
88- int count = m_searchCursors.size ();
97+ if (m_searchResults.isEmpty ()) {
98+ return 0 ;
99+ }
100+
101+ int count = m_searchResults.size ();
89102 m_currentIndex = (m_currentIndex - 1 + count) % count;
90103 scrollToCurrentIndex ();
91104 highlightMatches ();
@@ -95,7 +108,11 @@ int SearchableTextEdit::findPrev()
95108
96109int SearchableTextEdit::findLast ()
97110{
98- m_currentIndex = m_searchCursors.size () - 1 ;
111+ if (m_searchResults.isEmpty ()) {
112+ return 0 ;
113+ }
114+
115+ m_currentIndex = m_searchResults.size () - 1 ;
99116
100117 scrollToCurrentIndex ();
101118 highlightMatches ();
@@ -111,13 +128,15 @@ void SearchableTextEdit::resizeEvent(QResizeEvent *event)
111128
112129void SearchableTextEdit::highlightMatches ()
113130{
114- if (m_currentIndex < 0 || m_currentIndex >= m_searchCursors .size ()) {
131+ if (m_currentIndex < 0 || m_currentIndex >= m_searchResults .size ()) {
115132 this ->setExtraSelections ({});
116133 return ;
117134 }
118135
136+ QTextCursor cursor (this ->document ());
137+
119138 if (!m_highlightMatches) {
120- const QTextCursor cursor = m_searchCursors [m_currentIndex];
139+ mapCursorToResult ( cursor, m_searchResults [m_currentIndex]) ;
121140 QTextEdit::ExtraSelection selection;
122141 selection.format .setBackground (ConfigColor (" searchCurrent" ));
123142 selection.cursor = cursor;
@@ -127,26 +146,25 @@ void SearchableTextEdit::highlightMatches()
127146
128147 QPoint startPoint = QPoint (0 , 0 );
129148 int startPos = this ->cursorForPosition (startPoint).position ();
130- startPos -= m_searchedMatchLen;
131- startPos = startPos >= 0 ? startPos : 0 ;
132149
133150 QPoint endPoint = QPoint (this ->geometry ().width (), this ->geometry ().height ());
134151 auto endCursor = this ->cursorForPosition (endPoint);
135152 int endPos = endCursor.position ();
136- endPos += m_searchedMatchLen;
137153 endCursor.movePosition (QTextCursor::End);
138- endPos = endPos <= endCursor. position () ? endPos : endCursor.position ();
154+ int maxPos = endCursor.position ();
139155
140156 QList<QTextEdit::ExtraSelection> selections;
141- for (int i = 0 ; i < m_searchCursors.size (); ++i) {
142- const QTextCursor cursor = m_searchCursors[i];
143- int pos = cursor.selectionStart ();
157+ for (int i = 0 ; i < m_searchResults.size (); ++i) {
158+ const auto res = m_searchResults[i];
159+ mapCursorToResult (cursor, m_searchResults[i]);
160+ int sPos = std::max (startPos - res.length , 0 );
161+ int ePos = std::min (endPos + res.length , maxPos);
144162 if (i == m_currentIndex) {
145163 QTextEdit::ExtraSelection selection;
146164 selection.format .setBackground (ConfigColor (" searchCurrent" ));
147165 selection.cursor = cursor;
148166 selections.append (selection);
149- } else if (pos >= startPos && pos < endPos ) {
167+ } else if (cursor. selectionStart () >= sPos && cursor. selectionEnd () <= ePos ) {
150168 // only highlight visible matches
151169 QTextEdit::ExtraSelection selection;
152170 selection.format .setBackground (ConfigColor (" searchHighlight" ));
@@ -159,11 +177,12 @@ void SearchableTextEdit::highlightMatches()
159177
160178void SearchableTextEdit::scrollToCurrentIndex ()
161179{
162- if (m_currentIndex < 0 || m_currentIndex >= m_searchCursors .size ()) {
180+ if (m_currentIndex < 0 || m_currentIndex >= m_searchResults .size ()) {
163181 return ;
164182 }
165183
166- QTextCursor scrollCursor = m_searchCursors[m_currentIndex];
184+ QTextCursor scrollCursor (this ->document ());
185+ mapCursorToResult (scrollCursor, m_searchResults[m_currentIndex]);
167186 scrollCursor.setPosition (scrollCursor.selectionStart ());
168187 scrollCursor.clearSelection ();
169188 this ->setTextCursor (scrollCursor);
0 commit comments