Changeset View
Changeset View
Standalone View
Standalone View
src/search/katesearchbar.cpp
Show First 20 Lines • Show All 91 Lines • ▼ Show 20 Line(s) | 369 | case MatchNeutral: | |||
---|---|---|---|---|---|
370 | KColorScheme::adjustBackground(background, KColorScheme::NeutralBackground); | 370 | KColorScheme::adjustBackground(background, KColorScheme::NeutralBackground); | ||
371 | break; | 371 | break; | ||
372 | } | 372 | } | ||
373 | 373 | | |||
374 | // Update status label | 374 | // Update status label | ||
375 | if (m_incUi != nullptr) { | 375 | if (m_incUi != nullptr) { | ||
376 | QPalette foreground(m_incUi->status->palette()); | 376 | QPalette foreground(m_incUi->status->palette()); | ||
377 | switch (matchResult) { | 377 | switch (matchResult) { | ||
378 | case MatchFound: // FALLTHROUGH | 378 | case MatchFound: | ||
379 | m_incUi->next->setDisabled(false); | ||||
380 | m_incUi->prev->setDisabled(false); | ||||
381 | [[fallthrough]]; | ||||
379 | case MatchNothing: | 382 | case MatchNothing: | ||
380 | KColorScheme::adjustForeground(foreground, KColorScheme::NormalText, QPalette::WindowText, KColorScheme::Window); | 383 | KColorScheme::adjustForeground(foreground, KColorScheme::NormalText, QPalette::WindowText, KColorScheme::Window); | ||
381 | m_incUi->status->clear(); | 384 | m_incUi->status->clear(); | ||
382 | break; | 385 | break; | ||
383 | case MatchWrappedForward: | 386 | case MatchWrappedForward: | ||
384 | case MatchWrappedBackward: | 387 | case MatchWrappedBackward: | ||
385 | KColorScheme::adjustForeground(foreground, KColorScheme::NormalText, QPalette::WindowText, KColorScheme::Window); | 388 | KColorScheme::adjustForeground(foreground, KColorScheme::NormalText, QPalette::WindowText, KColorScheme::Window); | ||
386 | if (matchResult == MatchWrappedBackward) { | 389 | if (matchResult == MatchWrappedBackward) { | ||
Show All 33 Lines | |||||
420 | { | 423 | { | ||
421 | if (!m_incUi) { | 424 | if (!m_incUi) { | ||
422 | return; | 425 | return; | ||
423 | } | 426 | } | ||
424 | 427 | | |||
425 | // clear prior highlightings (deletes info message if present) | 428 | // clear prior highlightings (deletes info message if present) | ||
426 | clearHighlights(); | 429 | clearHighlights(); | ||
427 | 430 | | |||
428 | m_incUi->next->setDisabled(pattern.isEmpty()); | 431 | m_incUi->next->setDisabled(true); | ||
429 | m_incUi->prev->setDisabled(pattern.isEmpty()); | 432 | m_incUi->prev->setDisabled(true); | ||
430 | 433 | | |||
431 | KateMatch match(m_view->doc(), searchOptions()); | 434 | indicateMatch(MatchNothing); | ||
432 | 435 | | |||
433 | if (!pattern.isEmpty()) { | 436 | if (pattern.isEmpty()) { | ||
434 | // Find, first try | 437 | selectRange2(Range(m_incInitCursor, m_incInitCursor)); | ||
435 | const Range inputRange = KTextEditor::Range(m_incInitCursor, m_view->document()->documentEnd()); | 438 | return; | ||
436 | match.searchText(inputRange, pattern); | | |||
437 | } | 439 | } | ||
438 | 440 | | |||
439 | const bool wrap = !match.isValid() && !pattern.isEmpty(); | 441 | m_currentSearchRange = 0; | ||
440 | 442 | | |||
441 | if (wrap) { | 443 | const int newChunkOverlap = pattern.count(QLatin1Char('\n')); | ||
442 | // Find, second try | 444 | if (newChunkOverlap != m_chunkOverlap) { | ||
443 | const KTextEditor::Range inputRange = m_view->document()->documentRange(); | 445 | m_incSearchRanges.clear(); | ||
444 | match.searchText(inputRange, pattern); | 446 | } | ||
447 | | ||||
448 | if (!m_incSearchRanges.isEmpty()) { | ||||
449 | incrementalSearch(); | ||||
450 | return; | ||||
451 | } | ||||
452 | | ||||
453 | m_chunkOverlap = newChunkOverlap; | ||||
454 | | ||||
455 | // Build search range chunks in advance... | ||||
456 | const KTextEditor::Cursor chunkSize(2000, 0); | ||||
457 | const KTextEditor::Cursor chunkOverlap(m_chunkOverlap, 0); // Consider cases with multi line pattern | ||||
458 | const int fuzzyChunk = chunkSize.line() / 3; // To avoid too small chunks, so expand the last by 30% when possible | ||||
459 | // ...starting from current cursor position down to document end... | ||||
460 | KTextEditor::Cursor fromPos = m_incInitCursor; | ||||
461 | KTextEditor::Cursor toPos = KTextEditor::Cursor(m_incInitCursor.line() + chunkSize.line(), 0); | ||||
462 | int lastLine = m_view->document()->documentEnd().line() - fuzzyChunk - 1; | ||||
463 | forever { | ||||
464 | if (toPos.line() > lastLine) { | ||||
465 | toPos = m_view->document()->documentEnd(); | ||||
466 | m_incSearchRanges.append(KTextEditor::Range(fromPos, toPos)); | ||||
467 | break; | ||||
468 | } | ||||
469 | m_incSearchRanges.append(KTextEditor::Range(fromPos, toPos)); | ||||
470 | fromPos = toPos - chunkOverlap; | ||||
471 | toPos += chunkSize; | ||||
472 | } | ||||
473 | | ||||
474 | // ...continuing from top of document down to current cursor position | ||||
475 | fromPos = KTextEditor::Cursor(0, 0); | ||||
476 | toPos = chunkSize; | ||||
477 | lastLine = m_incInitCursor.line() - fuzzyChunk - 1; | ||||
478 | forever { | ||||
479 | if (toPos.line() > lastLine) { | ||||
480 | // Expand last chunk to end of current line to ensure we have a match when cursor is inside of pattern | ||||
481 | toPos = KTextEditor::Cursor(m_incInitCursor.line(), m_view->document()->lineLength(m_incInitCursor.line())); | ||||
482 | toPos += chunkOverlap; | ||||
483 | toPos = qMin(toPos, m_view->document()->documentEnd()); | ||||
484 | m_incSearchRanges.append(KTextEditor::Range(fromPos, toPos)); | ||||
485 | break; | ||||
486 | } | ||||
487 | m_incSearchRanges.append(KTextEditor::Range(fromPos, toPos)); | ||||
488 | fromPos = toPos - chunkOverlap; | ||||
489 | toPos += chunkSize; | ||||
490 | } | ||||
491 | | ||||
492 | incrementalSearch(); | ||||
493 | } | ||||
494 | | ||||
495 | void KateSearchBar::incrementalSearch() | ||||
496 | { | ||||
497 | if (m_incSearchRanges.size() <= m_currentSearchRange) { | ||||
498 | // Cursor was changed or user typed too fast | ||||
499 | return; | ||||
500 | } | ||||
501 | | ||||
502 | const Range range = m_incSearchRanges.at(m_currentSearchRange++); | ||||
503 | | ||||
504 | if (hasRangeMatch(range)) { | ||||
505 | // We are done, we have a winner | ||||
506 | return; | ||||
445 | } | 507 | } | ||
446 | 508 | | |||
447 | const MatchResult matchResult = match.isValid() ? (wrap ? MatchWrappedForward : MatchFound) : | 509 | if (m_incSearchRanges.size() == m_currentSearchRange) { | ||
448 | pattern.isEmpty() ? MatchNothing : | 510 | // We are done, nothing found | ||
449 | MatchMismatch; | 511 | selectRange2(Range::invalid()); | ||
512 | indicateMatch(MatchMismatch); | ||||
513 | } else { | ||||
514 | QTimer::singleShot(0, this, &KateSearchBar::incrementalSearch); | ||||
515 | } | ||||
516 | } | ||||
517 | | ||||
518 | // TODO parameter not needed, func could merged with incrementalSearch() | ||||
519 | bool KateSearchBar::hasRangeMatch(const KTextEditor::Range &range) | ||||
520 | { | ||||
521 | KateMatch match(m_view->doc(), searchOptions()); | ||||
522 | match.searchText(range, searchPattern()); | ||||
450 | 523 | | |||
451 | const Range selectionRange = pattern.isEmpty() ? Range(m_incInitCursor, m_incInitCursor) : | 524 | if (!match.isValid()) { | ||
452 | match.isValid() ? match.range() : | 525 | return false; | ||
453 | Range::invalid(); | 526 | } | ||
454 | 527 | | |||
528 | indicateMatch(MatchFound); | ||||
455 | // don't update m_incInitCursor when we move the cursor | 529 | // don't update m_incInitCursor when we move the cursor | ||
456 | disconnect(m_view, &KTextEditor::View::cursorPositionChanged, this, &KateSearchBar::updateIncInitCursor); | 530 | disconnect(m_view, &KTextEditor::View::cursorPositionChanged, this, &KateSearchBar::updateIncInitCursor); | ||
457 | selectRange2(selectionRange); | 531 | selectRange2(match.range()); | ||
458 | connect(m_view, &KTextEditor::View::cursorPositionChanged, this, &KateSearchBar::updateIncInitCursor); | 532 | connect(m_view, &KTextEditor::View::cursorPositionChanged, this, &KateSearchBar::updateIncInitCursor); | ||
459 | 533 | | |||
460 | indicateMatch(matchResult); | 534 | return true; | ||
461 | } | 535 | } | ||
462 | 536 | | |||
463 | void KateSearchBar::setMatchCase(bool matchCase) | 537 | void KateSearchBar::setMatchCase(bool matchCase) | ||
464 | { | 538 | { | ||
465 | if (this->matchCase() == matchCase) { | 539 | if (this->matchCase() == matchCase) { | ||
466 | return; | 540 | return; | ||
467 | } | 541 | } | ||
468 | 542 | | |||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Line(s) | 779 | { | |||
708 | m_powerUi->findPrev->setEnabled(isPatternValid()); | 782 | m_powerUi->findPrev->setEnabled(isPatternValid()); | ||
709 | m_powerUi->replaceNext->setEnabled(isPatternValid()); | 783 | m_powerUi->replaceNext->setEnabled(isPatternValid()); | ||
710 | m_powerUi->replaceAll->setEnabled(isPatternValid()); | 784 | m_powerUi->replaceAll->setEnabled(isPatternValid()); | ||
711 | m_powerUi->findAll->setEnabled(isPatternValid()); | 785 | m_powerUi->findAll->setEnabled(isPatternValid()); | ||
712 | } | 786 | } | ||
713 | 787 | | |||
714 | void KateSearchBar::addCurrentTextToHistory(QComboBox *combo) | 788 | void KateSearchBar::addCurrentTextToHistory(QComboBox *combo) | ||
715 | { | 789 | { | ||
790 | // Don't trigger editTextChanged/onIncPatternChanged | ||||
791 | const QSignalBlocker blocker(combo); | ||||
792 | | ||||
716 | const QString text = combo->currentText(); | 793 | const QString text = combo->currentText(); | ||
717 | const int index = combo->findText(text); | 794 | const int index = combo->findText(text); | ||
718 | 795 | | |||
719 | if (index > 0) { | 796 | if (index > 0) { | ||
720 | combo->removeItem(index); | 797 | combo->removeItem(index); | ||
721 | } | 798 | } | ||
722 | if (index != 0) { | 799 | if (index != 0) { | ||
723 | combo->insertItem(0, text); | 800 | combo->insertItem(0, text); | ||
724 | combo->setCurrentIndex(0); | 801 | combo->setCurrentIndex(0); | ||
725 | } | | |||
726 | 802 | | |||
727 | // sync to application config | 803 | // sync to application config | ||
728 | KTextEditor::EditorPrivate::self()->saveSearchReplaceHistoryModels(); | 804 | KTextEditor::EditorPrivate::self()->saveSearchReplaceHistoryModels(); | ||
805 | } | ||||
729 | } | 806 | } | ||
730 | 807 | | |||
731 | void KateSearchBar::backupConfig(bool ofPower) | 808 | void KateSearchBar::backupConfig(bool ofPower) | ||
732 | { | 809 | { | ||
733 | if (ofPower) { | 810 | if (ofPower) { | ||
734 | m_powerMatchCase = m_powerUi->matchCase->isChecked(); | 811 | m_powerMatchCase = m_powerUi->matchCase->isChecked(); | ||
735 | m_powerMode = m_powerUi->searchMode->currentIndex(); | 812 | m_powerMode = m_powerUi->searchMode->currentIndex(); | ||
736 | } else { | 813 | } else { | ||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Line(s) | 1720 | { | |||
1658 | highlightReplacementAttribute->setForeground(foregroundColor); | 1735 | highlightReplacementAttribute->setForeground(foregroundColor); | ||
1659 | } | 1736 | } | ||
1660 | 1737 | | |||
1661 | void KateSearchBar::showEvent(QShowEvent *event) | 1738 | void KateSearchBar::showEvent(QShowEvent *event) | ||
1662 | { | 1739 | { | ||
1663 | // Update init cursor | 1740 | // Update init cursor | ||
1664 | if (m_incUi != nullptr) { | 1741 | if (m_incUi != nullptr) { | ||
1665 | m_incInitCursor = m_view->cursorPosition(); | 1742 | m_incInitCursor = m_view->cursorPosition(); | ||
1743 | m_incSearchRanges.clear(); | ||||
1666 | } | 1744 | } | ||
1667 | 1745 | | |||
1668 | updateSelectionOnly(); | 1746 | updateSelectionOnly(); | ||
1669 | KateViewBarWidget::showEvent(event); | 1747 | KateViewBarWidget::showEvent(event); | ||
1670 | } | 1748 | } | ||
1671 | 1749 | | |||
1672 | void KateSearchBar::updateSelectionOnly() | 1750 | void KateSearchBar::updateSelectionOnly() | ||
1673 | { | 1751 | { | ||
Show All 12 Lines | |||||
1686 | } | 1764 | } | ||
1687 | 1765 | | |||
1688 | void KateSearchBar::updateIncInitCursor() | 1766 | void KateSearchBar::updateIncInitCursor() | ||
1689 | { | 1767 | { | ||
1690 | if (m_incUi == nullptr) { | 1768 | if (m_incUi == nullptr) { | ||
1691 | return; | 1769 | return; | ||
1692 | } | 1770 | } | ||
1693 | 1771 | | |||
1694 | // Update init cursor | 1772 | // Update init cursor, ensure to update search ranges too | ||
1695 | m_incInitCursor = m_view->cursorPosition(); | 1773 | m_incInitCursor = m_view->cursorPosition(); | ||
1774 | m_incSearchRanges.clear(); | ||||
1696 | } | 1775 | } | ||
1697 | 1776 | | |||
1698 | void KateSearchBar::onPowerPatternContextMenuRequest(const QPoint &pos) | 1777 | void KateSearchBar::onPowerPatternContextMenuRequest(const QPoint &pos) | ||
1699 | { | 1778 | { | ||
1700 | const bool FOR_PATTERN = true; | 1779 | const bool FOR_PATTERN = true; | ||
1701 | showExtendedContextMenu(FOR_PATTERN, pos); | 1780 | showExtendedContextMenu(FOR_PATTERN, pos); | ||
1702 | } | 1781 | } | ||
1703 | 1782 | | |||
Show All 37 Lines |