diff --git a/src/SearchHistoryTask.cpp b/src/SearchHistoryTask.cpp index b8a3deb1..6a313a9d 100644 --- a/src/SearchHistoryTask.cpp +++ b/src/SearchHistoryTask.cpp @@ -1,223 +1,223 @@ /* Copyright 2006-2008 by Robert Knight Copyright 2009 by Thomas Dreibholz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "SearchHistoryTask.h" #include #include #include "TerminalCharacterDecoder.h" #include "Emulation.h" namespace Konsole { void SearchHistoryTask::addScreenWindow(Session* session , ScreenWindow* searchWindow) { _windows.insert(session, searchWindow); } void SearchHistoryTask::execute() { auto iter = QMapIterator,ScreenWindowPtr>(_windows); while (iter.hasNext()) { iter.next(); executeOnScreenWindow(iter.key() , iter.value()); } } -void SearchHistoryTask::executeOnScreenWindow(const QPointer &session , ScreenWindowPtr window) +void SearchHistoryTask::executeOnScreenWindow(const QPointer &session , const ScreenWindowPtr& window) { Q_ASSERT(session); Q_ASSERT(window); Emulation* emulation = session->emulation(); if (!_regExp.pattern().isEmpty()) { int pos = -1; const bool forwards = (_direction == Enum::ForwardsSearch); 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 QTextStream searchStream(&string); PlainTextDecoder decoder; decoder.setRecordLinePositions(true); //setup first and last lines depending on search direction int line = startLine; //read through and search history in blocks of 10K lines. //this balances the need to retrieve lots of data from the history each time //(for efficient searching) //without using silly amounts of memory if the history is very large. const int maxDelta = qMin(window->lineCount(), 10000); int delta = forwards ? maxDelta : -maxDelta; int endLine = line; bool hasWrapped = false; // set to true when we reach the top/bottom // of the output and continue from the other // end //loop through history in blocks of lines. do { // ensure that application does not appear to hang // if searching through a lengthy output QApplication::processEvents(); // calculate lines to search in this iteration if (hasWrapped) { if (endLine == lastLine) { line = 0; } else if (endLine == 0) { line = lastLine; } endLine += delta; if (forwards) { endLine = qMin(startLine , endLine); } else { endLine = qMax(startLine , endLine); } } else { endLine += delta; if (endLine > lastLine) { hasWrapped = true; endLine = lastLine; } else if (endLine < 0) { hasWrapped = true; endLine = 0; } } decoder.begin(&searchStream); emulation->writeToStream(&decoder, qMin(endLine, line) , qMax(endLine, line)); decoder.end(); // line number search below assumes that the buffer ends with a new-line string.append(QLatin1Char('\n')); if (forwards) { pos = string.indexOf(_regExp); } else { pos = string.lastIndexOf(_regExp); } //if a match is found, position the cursor on that line and update the screen if (pos != -1) { int newLines = 0; QList linePositions = decoder.linePositions(); while (newLines < linePositions.count() && linePositions[newLines] <= pos) { newLines++; } // ignore the new line at the start of the buffer newLines--; int findPos = qMin(line, endLine) + newLines; highlightResult(window, findPos); emit completed(true); return; } //clear the current block of text and move to the next one string.clear(); line = endLine; } while (startLine != endLine); // if no match was found, clear selection to indicate this window->clearSelection(); window->notifyOutputChanged(); } emit completed(false); } -void SearchHistoryTask::highlightResult(ScreenWindowPtr window , int findPos) +void SearchHistoryTask::highlightResult(const ScreenWindowPtr& window , int findPos) { //work out how many lines into the current block of text the search result was found //- looks a little painful, but it only has to be done once per search. ////qDebug() << "Found result at line " << findPos; //update display to show area of history containing selection 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(Enum::BackwardsSearch) , _startLine(0) { } void SearchHistoryTask::setSearchDirection(Enum::SearchDirection direction) { _direction = direction; } void SearchHistoryTask::setStartLine(int line) { _startLine = line; } Enum::SearchDirection SearchHistoryTask::searchDirection() const { return _direction; } void SearchHistoryTask::setRegExp(const QRegularExpression &expression) { _regExp = expression; } QRegularExpression SearchHistoryTask::regExp() const { return _regExp; } } diff --git a/src/SearchHistoryTask.h b/src/SearchHistoryTask.h index b31f6aa7..16d06fca 100644 --- a/src/SearchHistoryTask.h +++ b/src/SearchHistoryTask.h @@ -1,102 +1,102 @@ /* Copyright 2006-2008 by Robert Knight Copyright 2009 by Thomas Dreibholz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef SEARCHHISTORYTASK_H #define SEARCHHISTORYTASK_H #include #include #include #include "SessionTask.h" #include "Enumeration.h" #include "ScreenWindow.h" #include "Session.h" namespace Konsole { //class SearchHistoryThread; /** * A task which searches through the output of sessions for matches for a given regular expression. * SearchHistoryTask operates on ScreenWindow instances rather than sessions added by addSession(). * A screen window can be added to the list to search using addScreenWindow() * * When execute() is called, the search begins in the direction specified by searchDirection(), * starting at the position of the current selection. * * FIXME - This is not a proper implementation of SessionTask, in that it ignores sessions specified * with addSession() * * TODO - Implementation requirements: * May provide progress feedback to the user when searching very large output logs. */ class SearchHistoryTask : public SessionTask { Q_OBJECT public: /** * Constructs a new search task. */ explicit SearchHistoryTask(QObject *parent = nullptr); /** Adds a screen window to the list to search when execute() is called. */ void addScreenWindow(Session *session, ScreenWindow *searchWindow); /** Sets the regular expression which is searched for when execute() is called */ void setRegExp(const QRegularExpression &expression); /** Returns the regular expression which is searched for when execute() is called */ QRegularExpression regExp() const; /** Specifies the direction to search in when execute() is called. */ void setSearchDirection(Enum::SearchDirection direction); /** Returns the current search direction. See setSearchDirection(). */ Enum::SearchDirection searchDirection() const; /** The line from which the search will be done **/ void setStartLine(int line); /** * Performs a search through the session's history, starting at the position * of the current selection, in the direction specified by setSearchDirection(). * * If it finds a match, the ScreenWindow specified in the constructor is * scrolled to the position where the match occurred and the selection * is set to the matching text. execute() then returns immediately. * * To continue the search looking for further matches, call execute() again. */ void execute() Q_DECL_OVERRIDE; private: using ScreenWindowPtr = QPointer; - void executeOnScreenWindow(const QPointer &session, ScreenWindowPtr window); - void highlightResult(ScreenWindowPtr window, int findPos); + void executeOnScreenWindow(const QPointer &session, const ScreenWindowPtr& window); + void highlightResult(const ScreenWindowPtr& window, int findPos); QMap< QPointer, ScreenWindowPtr > _windows; QRegularExpression _regExp; Enum::SearchDirection _direction; int _startLine; }; } #endif