From aa42a27ef33303bf5a279ea195758323724a6fc0 Mon Sep 17 00:00:00 2001 From: Harald Hvaal Date: Sat, 27 Jul 2013 09:39:27 +0200 Subject: [PATCH] Various search improvements - Do not automatically reset the search start line on search hits This was causing the annoying behavior that if you were to pause while typing in a search term, and it would actually find a hit, then you would be searching for the term a second time once you finish typing. This commit introduces two new behaviors: 1. When you show the search bar, all searching will be done from the first visible line in the terminal. 2. This start position is only reset when you advance to the next result, by pressing "next", "previous", or the shortcuts RETURN or SHIFT-RETURN - When the view scrolls to a result, it will appear centered. - When showing the search bar, do not invoke a search, only apply the highlight filters - Add "search from beginning/end" button This will scroll to the top/bottom before searching Ctrl+return is also bound to this action - Text highlighted by mouse will be set as the current search text when the incremental search bar is opened - Add "Search backwards" to search bar options Button text is swapped according to reverse search switch --- src/IncrementalSearchBar.cpp | 89 +++++++++++++++------ src/IncrementalSearchBar.h | 14 +++- src/ScreenWindow.cpp | 17 ++++ src/ScreenWindow.h | 10 +++ src/SessionController.cpp | 149 +++++++++++++++++++++++++++-------- src/SessionController.h | 16 ++++ src/TerminalDisplay.cpp | 26 +++++- src/TerminalDisplay.h | 3 + 8 files changed, 268 insertions(+), 56 deletions(-) diff --git a/src/IncrementalSearchBar.cpp b/src/IncrementalSearchBar.cpp index 79a28773c..627b03af2 100644 --- a/src/IncrementalSearchBar.cpp +++ b/src/IncrementalSearchBar.cpp @@ -42,6 +42,10 @@ IncrementalSearchBar::IncrementalSearchBar(QWidget* aParent) , _caseSensitive(0) , _regExpression(0) , _highlightMatches(0) + , _reverseSearch(0) + , _findNextButton(0) + , _findPreviousButton(0) + , _searchFromButton(0) { QHBoxLayout* barLayout = new QHBoxLayout(this); @@ -74,21 +78,24 @@ IncrementalSearchBar::IncrementalSearchBar(QWidget* aParent) connect(_searchEdit , SIGNAL(clearButtonClicked()) , this , SLOT(clearLineEdit())); connect(_searchEdit , SIGNAL(textChanged(QString)) , _searchTimer , SLOT(start())); - QToolButton* findNext = new QToolButton(this); - findNext->setObjectName(QLatin1String("find-next-button")); - findNext->setText(i18nc("@action:button Go to the next phrase", "Next")); - findNext->setIcon(KIcon("go-down-search")); - findNext->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - findNext->setToolTip(i18nc("@info:tooltip", "Find the next match for the current search phrase")); - connect(findNext , SIGNAL(clicked()) , this , SIGNAL(findNextClicked())); + _findNextButton = new QToolButton(this); + _findNextButton->setObjectName(QLatin1String("find-next-button")); + _findNextButton->setText(i18nc("@action:button Go to the next phrase", "Next")); + _findNextButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + _findNextButton->setToolTip(i18nc("@info:tooltip", "Find the next match for the current search phrase")); + connect(_findNextButton , SIGNAL(clicked()) , this , SIGNAL(findNextClicked())); - QToolButton* findPrev = new QToolButton(this); - findPrev->setObjectName(QLatin1String("find-previous-button")); - findPrev->setText(i18nc("@action:button Go to the previous phrase", "Previous")); - findPrev->setIcon(KIcon("go-up-search")); - findPrev->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - findPrev->setToolTip(i18nc("@info:tooltip", "Find the previous match for the current search phrase")); - connect(findPrev , SIGNAL(clicked()) , this , SIGNAL(findPreviousClicked())); + _findPreviousButton = new QToolButton(this); + _findPreviousButton->setObjectName(QLatin1String("find-previous-button")); + _findPreviousButton->setText(i18nc("@action:button Go to the previous phrase", "Previous")); + _findPreviousButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + _findPreviousButton->setToolTip(i18nc("@info:tooltip", "Find the previous match for the current search phrase")); + connect(_findPreviousButton , SIGNAL(clicked()) , this , SIGNAL(findPreviousClicked())); + + + _searchFromButton = new QToolButton(this); + _searchFromButton->setObjectName(QLatin1String("search-from-button")); + connect(_searchFromButton , SIGNAL(clicked()) , this , SIGNAL(searchFromClicked())); QToolButton* optionsButton = new QToolButton(this); optionsButton->setObjectName(QLatin1String("find-options-button")); @@ -102,8 +109,9 @@ IncrementalSearchBar::IncrementalSearchBar(QWidget* aParent) barLayout->addWidget(closeButton); barLayout->addWidget(findLabel); barLayout->addWidget(_searchEdit); - barLayout->addWidget(findNext); - barLayout->addWidget(findPrev); + barLayout->addWidget(_findNextButton); + barLayout->addWidget(_findPreviousButton); + barLayout->addWidget(_searchFromButton); barLayout->addWidget(optionsButton); // Fill the options menu @@ -128,16 +136,43 @@ IncrementalSearchBar::IncrementalSearchBar(QWidget* aParent) connect(_highlightMatches, SIGNAL(toggled(bool)), this, SIGNAL(highlightMatchesToggled(bool))); + _reverseSearch = optionsMenu->addAction(i18n("Search backwards")); + _reverseSearch->setCheckable(true); + _reverseSearch->setToolTip(i18n("Sets whether search should start from the bottom")); + _reverseSearch->setChecked(true); + connect(_reverseSearch, SIGNAL(toggled(bool)), + this, SLOT(updateButtonsAccordingToReverseSearchSetting())); + updateButtonsAccordingToReverseSearchSetting(); + barLayout->addStretch(); barLayout->setContentsMargins(4, 4, 4, 4); setLayout(barLayout); } + void IncrementalSearchBar::notifySearchChanged() { emit searchChanged(searchText()); } + +void IncrementalSearchBar::updateButtonsAccordingToReverseSearchSetting() +{ + Q_ASSERT(_reverseSearch); + if (_reverseSearch->isChecked()) { + _searchFromButton->setText(i18nc("@action:button Search from bottom", "From bottom")); + _searchFromButton->setToolTip(i18n("Search for the current search phrase from the bottom")); + _findNextButton->setIcon(KIcon("go-up-search")); + _findPreviousButton->setIcon(KIcon("go-down-search")); + } else { + _searchFromButton->setText(i18nc("@action:button Search from top", "From top")); + _searchFromButton->setToolTip(i18n("Search for the current search phrase from the top")); + _findNextButton->setIcon(KIcon("go-down-search")); + _findPreviousButton->setIcon(KIcon("go-up-search")); + } + +} + QString IncrementalSearchBar::searchText() { return _searchEdit->text(); @@ -161,12 +196,17 @@ bool IncrementalSearchBar::eventFilter(QObject* watched , QEvent* aEvent) } if (keyEvent->key() == Qt::Key_Return && !keyEvent->modifiers()) { - emit searchReturnPressed(_searchEdit->text()); + _findNextButton->click(); return true; } if ((keyEvent->key() == Qt::Key_Return) && (keyEvent->modifiers() == Qt::ShiftModifier)) { - emit searchShiftPlusReturnPressed(); + _findPreviousButton->click(); + return true; + } + + if ((keyEvent->key() == Qt::Key_Return) && (keyEvent->modifiers() == Qt::ControlModifier)) { + _searchFromButton->click(); return true; } } @@ -180,9 +220,7 @@ void IncrementalSearchBar::setVisible(bool visible) QWidget::setVisible(visible); if (visible) { - //TODO - Check if this is the correct reason value to use here - _searchEdit->setFocus(Qt::ActiveWindowFocusReason); - _searchEdit->selectAll(); + focusLineEdit(); } } @@ -212,13 +250,20 @@ void IncrementalSearchBar::clearLineEdit() _searchEdit->setStyleSheet(QString()); } +void IncrementalSearchBar::focusLineEdit() +{ + _searchEdit->setFocus(Qt::ActiveWindowFocusReason); + _searchEdit->selectAll(); +} + const QBitArray IncrementalSearchBar::optionsChecked() { - QBitArray options(3, 0); + QBitArray options(4, 0); if (_caseSensitive->isChecked()) options.setBit(MatchCase); if (_regExpression->isChecked()) options.setBit(RegExp); if (_highlightMatches->isChecked()) options.setBit(HighlightMatches); + if (_reverseSearch->isChecked()) options.setBit(ReverseSearch); return options; } diff --git a/src/IncrementalSearchBar.h b/src/IncrementalSearchBar.h index d0661a5ae..44be26c07 100644 --- a/src/IncrementalSearchBar.h +++ b/src/IncrementalSearchBar.h @@ -28,6 +28,7 @@ class QAction; class QLabel; class QTimer; class KLineEdit; +class QToolButton; namespace Konsole { @@ -66,7 +67,9 @@ public: /** Searches are case-sensitive or not */ MatchCase = 1, /** Searches use regular expressions */ - RegExp = 2 + RegExp = 2, + /** Search from the bottom and up **/ + ReverseSearch = 3 }; /** @@ -95,6 +98,8 @@ public: void setSearchText(const QString& text); + void focusLineEdit(); + // reimplemented virtual void setVisible(bool visible); signals: @@ -104,6 +109,8 @@ signals: void findNextClicked(); /** Emitted when the user clicks the button to find the previous match */ void findPreviousClicked(); + /** The search from beginning/end button */ + void searchFromClicked(); /** * Emitted when the user toggles the checkbox to indicate whether * matches for the search text should be highlighted @@ -134,12 +141,17 @@ public slots: private slots: void notifySearchChanged(); + void updateButtonsAccordingToReverseSearchSetting(); private: KLineEdit* _searchEdit; QAction* _caseSensitive; QAction* _regExpression; QAction* _highlightMatches; + QAction* _reverseSearch; + QToolButton* _findNextButton; + QToolButton* _findPreviousButton; + QToolButton* _searchFromButton; QTimer* _searchTimer; }; diff --git a/src/ScreenWindow.cpp b/src/ScreenWindow.cpp index 92804302c..e2bf5c145 100644 --- a/src/ScreenWindow.cpp +++ b/src/ScreenWindow.cpp @@ -32,10 +32,12 @@ ScreenWindow::ScreenWindow(QObject* parent) , _bufferNeedsUpdate(true) , _windowLines(1) , _currentLine(0) + , _currentResultLine(-1) , _trackOutput(true) , _scrollCount(0) { } + ScreenWindow::~ScreenWindow() { delete[] _windowBuffer; @@ -211,6 +213,21 @@ int ScreenWindow::currentLine() const return qBound(0, _currentLine, lineCount() - windowLines()); } +int ScreenWindow::currentResultLine() const +{ + return _currentResultLine; +} + +void ScreenWindow::setCurrentResultLine(int line) +{ + if (_currentResultLine == line) { + return; + } + + _currentResultLine = line; + emit currentResultLineChanged(); +} + void ScreenWindow::scrollBy(RelativeScrollMode mode, int amount, bool fullPage) { if (mode == ScrollLines) { diff --git a/src/ScreenWindow.h b/src/ScreenWindow.h index 89fe7bed7..22b32ea76 100644 --- a/src/ScreenWindow.h +++ b/src/ScreenWindow.h @@ -113,6 +113,13 @@ public: */ QRect scrollRegion() const; + + /** + * What line the next search will start from + */ + void setCurrentResultLine(int line); + int currentResultLine() const; + /** * Sets the start of the selection to the given @p line and @p column within * the window. @@ -241,6 +248,8 @@ signals: */ void outputChanged(); + void currentResultLineChanged(); + /** * Emitted when the screen window is scrolled to a different position. * @@ -262,6 +271,7 @@ private: int _windowLines; int _currentLine; // see scrollTo() , currentLine() + int _currentResultLine; bool _trackOutput; // see setTrackOutput() , trackOutput() int _scrollCount; // count of lines which the window has been scrolled by since // the last call to resetScrollCount() diff --git a/src/SessionController.cpp b/src/SessionController.cpp index 88fc50c6a..d7745bcfb 100644 --- a/src/SessionController.cpp +++ b/src/SessionController.cpp @@ -112,6 +112,8 @@ SessionController::SessionController(Session* session , TerminalDisplay* view, Q , _findNextAction(0) , _findPreviousAction(0) , _urlFilterUpdateRequired(false) + , _searchStartLine(0) + , _prevSearchResultLine(0) , _searchBar(0) , _codecAction(0) , _switchProfileMenu(0) @@ -526,6 +528,7 @@ void SessionController::setSearchBar(IncrementalSearchBar* searchBar) _searchBar = searchBar; if (_searchBar) { connect(_searchBar, SIGNAL(closeClicked()), this, SLOT(searchClosed())); + connect(_searchBar, SIGNAL(searchFromClicked()), this, SLOT(searchFrom())); connect(_searchBar, SIGNAL(findNextClicked()), this, SLOT(findNextInHistory())); connect(_searchBar, SIGNAL(findPreviousClicked()), this, SLOT(findPreviousInHistory())); connect(_searchBar, SIGNAL(highlightMatchesToggled(bool)) , this , SLOT(highlightMatches(bool))); @@ -1084,6 +1087,17 @@ void SessionController::searchClosed() searchHistory(false); } +void SessionController::setSearchStartToWindowCurrentLine() +{ + setSearchStartTo(-1); +} + +void SessionController::setSearchStartTo(int line) +{ + _searchStartLine = line; + _prevSearchResultLine = line; +} + void SessionController::listenForScreenWindowUpdates() { if (_listenForScreenWindowUpdates) @@ -1093,6 +1107,8 @@ void SessionController::listenForScreenWindowUpdates() SLOT(updateSearchFilter())); connect(_view->screenWindow(), SIGNAL(scrolled(int)), this, SLOT(updateSearchFilter())); + connect(_view->screenWindow(), SIGNAL(currentResultLineChanged()), _view, + SLOT(update())); _listenForScreenWindowUpdates = true; } @@ -1106,9 +1122,12 @@ void SessionController::updateSearchFilter() void SessionController::searchBarEvent() { + QString selectedText = _view->screenWindow()->selectedText(true, true); + if (!selectedText.isEmpty()) + _searchBar->setSearchText(selectedText); + if (_searchBar->isVisible()) { - // refresh focus - _searchBar->setVisible(true); + _searchBar->focusLineEdit(); } else { searchHistory(true); _isSearchBarEnabled = true; @@ -1119,10 +1138,13 @@ void SessionController::enableSearchBar(bool showSearchBar) { if (!_searchBar) return; + + if (showSearchBar && !_searchBar->isVisible()) { + setSearchStartToWindowCurrentLine(); + } + _searchBar->setVisible(showSearchBar); if (showSearchBar) { - _searchBar->clearLineEdit(); - _searchBar->setSearchText(_searchText); connect(_searchBar, SIGNAL(searchChanged(QString)), this, SLOT(searchTextChanged(QString))); connect(_searchBar, SIGNAL(searchReturnPressed(QString)), this, @@ -1136,9 +1158,32 @@ void SessionController::enableSearchBar(bool showSearchBar) SLOT(findPreviousInHistory())); disconnect(_searchBar, SIGNAL(searchShiftPlusReturnPressed()), this, SLOT(findNextInHistory())); + if (_view && _view->screenWindow()) { + _view->screenWindow()->setCurrentResultLine(-1); + } } } + +bool SessionController::reverseSearchChecked() const +{ + Q_ASSERT(_searchBar); + + QBitArray options = _searchBar->optionsChecked(); + return options.at(IncrementalSearchBar::ReverseSearch); +} + +QRegExp SessionController::regexpFromSearchBarOptions() +{ + QBitArray options = _searchBar->optionsChecked(); + + Qt::CaseSensitivity caseHandling = options.at(IncrementalSearchBar::MatchCase) ? Qt::CaseSensitive : Qt::CaseInsensitive; + QRegExp::PatternSyntax syntax = options.at(IncrementalSearchBar::RegExp) ? QRegExp::RegExp : QRegExp::FixedString; + + QRegExp regExp(_searchBar->searchText(), caseHandling , syntax); + return regExp; +} + // searchHistory() may be called either as a result of clicking a menu item or // as a result of changing the search bar widget void SessionController::searchHistory(bool showSearchBar) @@ -1152,13 +1197,9 @@ void SessionController::searchHistory(bool showSearchBar) listenForScreenWindowUpdates(); _searchFilter = new RegExpFilter(); + _searchFilter->setRegExp(regexpFromSearchBarOptions()); _view->filterChain()->addFilter(_searchFilter); - - // invoke search for matches for the current search text - const QString& currentSearchText = _searchBar->searchText(); - if (!currentSearchText.isEmpty()) { - searchTextChanged(currentSearchText); - } + _view->processFilters(); setFindNextPrevEnabled(true); } else { @@ -1170,6 +1211,7 @@ void SessionController::searchHistory(bool showSearchBar) } } } + void SessionController::setFindNextPrevEnabled(bool enabled) { _findNextAction->setEnabled(enabled); @@ -1184,15 +1226,19 @@ void SessionController::searchTextChanged(const QString& text) _searchText = text; - if (text.isEmpty()) + if (text.isEmpty()) { _view->screenWindow()->clearSelection(); + _view->screenWindow()->scrollTo(_searchStartLine); + } // update search. this is called even when the text is // empty to clear the view's filters - beginSearch(text , SearchHistoryTask::BackwardsSearch); + beginSearch(text , reverseSearchChecked() ? SearchHistoryTask::BackwardsSearch : SearchHistoryTask::ForwardsSearch); } void SessionController::searchCompleted(bool success) { + _prevSearchResultLine = _view->screenWindow()->currentResultLine(); + if (_searchBar) _searchBar->setFoundMatch(success); } @@ -1202,15 +1248,19 @@ void SessionController::beginSearch(const QString& text , int direction) Q_ASSERT(_searchBar); Q_ASSERT(_searchFilter); - QBitArray options = _searchBar->optionsChecked(); - - Qt::CaseSensitivity caseHandling = options.at(IncrementalSearchBar::MatchCase) ? Qt::CaseSensitive : Qt::CaseInsensitive; - QRegExp::PatternSyntax syntax = options.at(IncrementalSearchBar::RegExp) ? QRegExp::RegExp : QRegExp::FixedString; - - QRegExp regExp(text , caseHandling , syntax); + QRegExp regExp = regexpFromSearchBarOptions(); _searchFilter->setRegExp(regExp); + if (_searchStartLine == -1) { + if (direction == SearchHistoryTask::ForwardsSearch) { + setSearchStartTo(_view->screenWindow()->currentLine()); + } else { + setSearchStartTo(_view->screenWindow()->currentLine() + _view->screenWindow()->windowLines()); + } + } + if (!regExp.isEmpty()) { + _view->screenWindow()->setCurrentResultLine(-1); SearchHistoryTask* task = new SearchHistoryTask(this); connect(task, SIGNAL(completed(bool)), this, SLOT(searchCompleted(bool))); @@ -1218,6 +1268,7 @@ void SessionController::beginSearch(const QString& text , int direction) task->setRegExp(regExp); task->setSearchDirection((SearchHistoryTask::SearchDirection)direction); task->setAutoDelete(true); + task->setStartLine(_searchStartLine); task->addScreenWindow(_session , _view->screenWindow()); task->execute(); } else if (text.isEmpty()) { @@ -1237,19 +1288,38 @@ void SessionController::highlightMatches(bool highlight) _view->update(); } + +void SessionController::searchFrom() +{ + Q_ASSERT(_searchBar); + Q_ASSERT(_searchFilter); + + if (reverseSearchChecked()) { + setSearchStartTo(_view->screenWindow()->lineCount()); + } else { + setSearchStartTo(0); + } + + + beginSearch(_searchBar->searchText(), reverseSearchChecked() ? SearchHistoryTask::BackwardsSearch : SearchHistoryTask::ForwardsSearch); +} void SessionController::findNextInHistory() { Q_ASSERT(_searchBar); Q_ASSERT(_searchFilter); - beginSearch(_searchBar->searchText(), SearchHistoryTask::ForwardsSearch); + setSearchStartTo(_prevSearchResultLine); + + beginSearch(_searchBar->searchText(), reverseSearchChecked() ? SearchHistoryTask::BackwardsSearch : SearchHistoryTask::ForwardsSearch); } void SessionController::findPreviousInHistory() { Q_ASSERT(_searchBar); Q_ASSERT(_searchFilter); - beginSearch(_searchBar->searchText(), SearchHistoryTask::BackwardsSearch); + setSearchStartTo(_prevSearchResultLine); + + beginSearch(_searchBar->searchText(), reverseSearchChecked() ? SearchHistoryTask::ForwardsSearch : SearchHistoryTask::BackwardsSearch); } void SessionController::changeSearchMatch() { @@ -1258,7 +1328,7 @@ void SessionController::changeSearchMatch() // reset Selection for new case match _view->screenWindow()->clearSelection(); - beginSearch(_searchBar->searchText(), SearchHistoryTask::BackwardsSearch); + beginSearch(_searchBar->searchText(), reverseSearchChecked() ? SearchHistoryTask::BackwardsSearch : SearchHistoryTask::ForwardsSearch); } void SessionController::showHistoryOptions() { @@ -1734,18 +1804,20 @@ void SearchHistoryTask::executeOnScreenWindow(SessionPtr session , ScreenWindowP Emulation* emulation = session->emulation(); - int selectionColumn = 0; - int selectionLine = 0; - - window->getSelectionEnd(selectionColumn , selectionLine); - if (!_regExp.isEmpty()) { int pos = -1; const bool forwards = (_direction == ForwardsSearch); - int startLine = selectionLine + window->currentLine() + (forwards ? 1 : -1); - // Temporary fix for #205495 - if (startLine < 0) startLine = 0; const int lastLine = window->lineCount() - 1; + + int startLine; + if (forwards && (_startLine == lastLine)) { + startLine = 0; + } else if (!forwards && (_startLine == 0)) { + startLine = lastLine; + } else { + startLine = _startLine + (forwards ? 1 : -1); + } + QString string; //text stream to read history into string for pattern or regular expression searching @@ -1852,22 +1924,35 @@ void SearchHistoryTask::highlightResult(ScreenWindowPtr window , int findPos) //kDebug() << "Found result at line " << findPos; //update display to show area of history containing selection - window->scrollTo(findPos); - window->setSelectionStart(0 , findPos - window->currentLine() , false); - window->setSelectionEnd(window->columnCount() , findPos - window->currentLine()); + if ((findPos < window->currentLine()) || + (findPos >= (window->currentLine() + window->windowLines()))) { + int centeredScrollPos = findPos - window->windowLines() / 2; + if (centeredScrollPos < 0) { + centeredScrollPos = 0; + } + + window->scrollTo(centeredScrollPos); + } + window->setTrackOutput(false); window->notifyOutputChanged(); + window->setCurrentResultLine(findPos); } SearchHistoryTask::SearchHistoryTask(QObject* parent) : SessionTask(parent) , _direction(BackwardsSearch) + , _startLine(0) { } void SearchHistoryTask::setSearchDirection(SearchDirection direction) { _direction = direction; } +void SearchHistoryTask::setStartLine(int line) +{ + _startLine = line; +} SearchHistoryTask::SearchDirection SearchHistoryTask::searchDirection() const { return _direction; diff --git a/src/SessionController.h b/src/SessionController.h index 036e05349..b061e70de 100644 --- a/src/SessionController.h +++ b/src/SessionController.h @@ -126,6 +126,13 @@ public: */ bool isValid() const; + /** Set the start line from which the next search will be done **/ + void setSearchStartTo(int line); + + /** set start line to the first or last line (depending on the reverse search + * setting) in the terminal display **/ + void setSearchStartToWindowCurrentLine(); + /** * Sets the widget used for searches through the session's output. * @@ -228,6 +235,7 @@ private slots: void enableSearchBar(bool showSearchBar); void searchHistory(bool showSearchBar); void searchBarEvent(); + void searchFrom(); void findNextInHistory(); void findPreviousInHistory(); void changeSearchMatch(); @@ -286,6 +294,8 @@ private: // direction - value from SearchHistoryTask::SearchDirection enum to specify // the search direction void beginSearch(const QString& text , int direction); + QRegExp regexpFromSearchBarOptions(); + bool reverseSearchChecked() const; void setupCommonActions(); void setupExtraActions(); void removeSearchFilter(); // remove and delete the current search filter if set @@ -318,6 +328,8 @@ private: bool _urlFilterUpdateRequired; + int _searchStartLine; + int _prevSearchResultLine; QPointer _searchBar; KCodecAction* _codecAction; @@ -496,6 +508,9 @@ public: /** Returns the current search direction. See setSearchDirection(). */ SearchDirection searchDirection() const; + /** The line from which the search will be done **/ + void setStartLine(int startLine); + /** * Performs a search through the session's history, starting at the position * of the current selection, in the direction specified by setSearchDirection(). @@ -517,6 +532,7 @@ private: QMap< SessionPtr , ScreenWindowPtr > _windows; QRegExp _regExp; SearchDirection _direction; + int _startLine; //static QPointer _thread; }; diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp index acfddc176..9ec92aa34 100644 --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -116,6 +116,7 @@ void TerminalDisplay::setScreenWindow(ScreenWindow* window) if (_screenWindow) { connect(_screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties())); connect(_screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage())); + connect(_screenWindow , SIGNAL(currentResultLineChanged()) , this , SLOT(updateImage())); _screenWindow->setWindowLines(_lines); } } @@ -358,6 +359,8 @@ TerminalDisplay::TerminalDisplay(QWidget* parent) _scrollBar->setCursor(Qt::ArrowCursor); connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); + connect(_scrollBar, SIGNAL(sliderMoved(int)), + this, SLOT(viewScrolledByUser())); // setup timers for blinking text _blinkTextTimer = new QTimer(this); @@ -1169,6 +1172,7 @@ void TerminalDisplay::paintEvent(QPaintEvent* pe) true /* use opacity setting */); drawContents(paint, rect); } + drawCurrentResultRect(paint); drawInputMethodPreeditString(paint, preeditRect()); paintFilters(paint); } @@ -1310,7 +1314,9 @@ void TerminalDisplay::paintFilters(QPainter& painter) // drawn on top of them } else if (spot->type() == Filter::HotSpot::Marker) { //TODO - Do not use a hardcoded color for this - painter.fillRect(r, QBrush(QColor(255, 0, 0, 120))); + const bool isCurrentResultLine = (_screenWindow->currentResultLine() == (spot->startLine() + _screenWindow->currentLine())); + QColor color = isCurrentResultLine ? QColor(255, 255, 0, 120) : QColor(255, 0, 0, 120); + painter.fillRect(r, color); } } } @@ -1473,6 +1479,17 @@ void TerminalDisplay::drawContents(QPainter& paint, const QRect& rect) } } +void TerminalDisplay::drawCurrentResultRect(QPainter& painter) +{ + if(_screenWindow->currentResultLine() == -1) { + return; + } + + QRect r(0, (_screenWindow->currentResultLine() - _screenWindow->currentLine())*_fontHeight, + contentsRect().width(), _fontHeight); + painter.fillRect(r, QColor(0, 0, 255, 80)); +} + QRect TerminalDisplay::imageToWidget(const QRect& imageArea) const { QRect result; @@ -2458,6 +2475,7 @@ void TerminalDisplay::wheelEvent(QWheelEvent* ev) const bool canScroll = _scrollBar->maximum() > 0; if (canScroll) { _scrollBar->event(ev); + _sessionController->setSearchStartToWindowCurrentLine(); } else { // assume that each Up / Down key event will cause the terminal application // to scroll by one line. @@ -2494,6 +2512,11 @@ void TerminalDisplay::tripleClickTimeout() _possibleTripleClick = false; } +void TerminalDisplay::viewScrolledByUser() +{ + _sessionController->setSearchStartToWindowCurrentLine(); +} + void TerminalDisplay::mouseTripleClickEvent(QMouseEvent* ev) { if (!_screenWindow) return; @@ -2832,6 +2855,7 @@ void TerminalDisplay::scrollScreenWindow(enum ScreenWindow::RelativeScrollMode m _screenWindow->setTrackOutput(_screenWindow->atEndOfOutput()); updateLineProperties(); updateImage(); + viewScrolledByUser(); } void TerminalDisplay::keyPressEvent(QKeyEvent* event) diff --git a/src/TerminalDisplay.h b/src/TerminalDisplay.h index 100ffccc3..ad60cf985 100644 --- a/src/TerminalDisplay.h +++ b/src/TerminalDisplay.h @@ -668,6 +668,7 @@ private slots: void unmaskBell(); void swapFGBGColors(); void tripleClickTimeout(); // resets possibleTripleClick + void viewScrolledByUser(); /** * Called from the drag-and-drop popup. Causes the dropped URLs to be pasted as text. @@ -684,6 +685,8 @@ private: // drawTextFragment() or drawPrinterFriendlyTextFragment() // to draw the fragments void drawContents(QPainter& painter, const QRect& rect); + // draw a transparent rectangle over the line of the current match + void drawCurrentResultRect(QPainter& painter); // draws a section of text, all the text in this section // has a common color and style void drawTextFragment(QPainter& painter, const QRect& rect,