1 /* 2 * Copyright (C) 2009, 2010, 2011, 2012 Nicolas Bonnefon and other contributors 3 * 4 * This file is part of glogg. 5 * 6 * glogg is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * glogg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with glogg. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef LOGFILTEREDDATA_H 21 #define LOGFILTEREDDATA_H 22 23 #include <memory> 24 25 #include <QObject> 26 #include <QByteArray> 27 #include <QList> 28 #include <QStringList> 29 #include <QRegExp> 30 31 #include "abstractlogdata.h" 32 #include "logfiltereddataworkerthread.h" 33 #include "marks.h" 34 35 class LogData; 36 class Marks; 37 38 // A list of matches found in a LogData, it stores all the matching lines, 39 // which can be accessed using the AbstractLogData interface, together with 40 // the original line number where they were found. 41 // Constructing such objet does not start the search. 42 // This object should be constructed by a LogData. 43 class LogFilteredData : public AbstractLogData { 44 Q_OBJECT 45 46 public: 47 // Creates an empty LogFilteredData 48 LogFilteredData(); 49 // Constructor used by LogData 50 LogFilteredData( const LogData* logData ); 51 52 ~LogFilteredData(); 53 54 // Starts the async search, sending newDataAvailable() when new data found. 55 // If a search is already in progress this function will block until 56 // it is done, so the application should call interruptSearch() first. 57 void runSearch( const QRegExp& regExp ); 58 // Add to the existing search, starting at the line when the search was 59 // last stopped. Used when the file on disk has been added too. 60 void updateSearch(); 61 // Interrupt the running search if one is in progress. 62 // Nothing is done if no search is in progress. 63 void interruptSearch(); 64 // Clear the search and the list of results. 65 void clearSearch(); 66 // Returns the line number in the original LogData where the element 67 // 'index' was found. 68 qint64 getMatchingLineNumber( int index ) const; 69 // Returns whether the line number passed is in our list of matching ones. 70 bool isLineInMatchingList( qint64 lineNumber ); 71 72 // Returns the number of lines in the source log data 73 LineNumber getNbTotalLines() const; 74 // Returns the number of matches (independently of the visibility) 75 LineNumber getNbMatches() const; 76 // Returns the number of marks (independently of the visibility) 77 LineNumber getNbMarks() const; 78 79 // Returns the reason why the line at the passed index is in the filtered 80 // data. It can be because it is either a mark or a match. 81 enum FilteredLineType { Match, Mark }; 82 FilteredLineType filteredLineTypeByIndex( int index ) const; 83 84 // Marks interface (delegated to a Marks object) 85 86 // Add a mark at the given line, optionally identified by the given char 87 // If a mark for this char already exist, the previous one is replaced. 88 void addMark( qint64 line, QChar mark = QChar() ); 89 // Get the (unique) mark identified by the passed char. 90 qint64 getMark( QChar mark ) const; 91 // Returns wheither the passed line has a mark on it. 92 bool isLineMarked( qint64 line ) const; 93 // Delete the mark identified by the passed char. 94 void deleteMark( QChar mark ); 95 // Delete the mark present on the passed line or do nothing if there is 96 // none. 97 void deleteMark( qint64 line ); 98 // Completely clear the marks list. 99 void clearMarks(); 100 101 // Changes what the AbstractLogData returns via its getXLines/getNbLines 102 // API. 103 enum Visibility { MatchesOnly, MarksOnly, MarksAndMatches }; 104 void setVisibility( Visibility visibility ); 105 106 signals: 107 // Sent when the search has progressed, give the number of matches (so far) 108 // and the percentage of completion 109 void searchProgressed( int nbMatches, int progress ); 110 111 private slots: 112 void handleSearchProgressed( int NbMatches, int progress ); 113 114 private: 115 class FilteredItem; 116 117 // Implementation of virtual functions 118 QString doGetLineString( qint64 line ) const; 119 QString doGetExpandedLineString( qint64 line ) const; 120 QStringList doGetLines( qint64 first, int number ) const; 121 QStringList doGetExpandedLines( qint64 first, int number ) const; 122 qint64 doGetNbLine() const; 123 int doGetMaxLength() const; 124 int doGetLineLength( qint64 line ) const; 125 void doSetDisplayEncoding( const char* encoding ); 126 127 // List of the matching line numbers 128 SearchResultArray matching_lines_; 129 130 const LogData* sourceLogData_; 131 QRegExp currentRegExp_; 132 bool searchDone_; 133 int maxLength_; 134 int maxLengthMarks_; 135 // Number of lines of the LogData that has been searched for: 136 qint64 nbLinesProcessed_; 137 138 Visibility visibility_; 139 140 // Cache used to combine Marks and Matches 141 // when visibility_ == MarksAndMatches 142 // (QVector store actual objects instead of pointers) 143 mutable std::vector<FilteredItem> filteredItemsCache_; 144 mutable bool filteredItemsCacheDirty_; 145 146 LogFilteredDataWorkerThread workerThread_; 147 Marks marks_; 148 149 // Utility functions 150 LineNumber findLogDataLine( LineNumber lineNum ) const; 151 void regenerateFilteredItemsCache() const; 152 }; 153 154 // A class representing a Mark or Match. 155 // Conceptually it should be a base class for Mark and MatchingLine, 156 // but we implement it this way for performance reason as we create plenty of 157 // those everytime we refresh the cache. 158 // Specifically it allows to store this in the cache by value instead 159 // of pointer (less small allocations and no RTTI). 160 class LogFilteredData::FilteredItem { 161 public: 162 // A default ctor seems to be necessary for QVector 163 FilteredItem() 164 { lineNumber_ = 0; } 165 FilteredItem( LineNumber lineNumber, FilteredLineType type ) 166 { lineNumber_ = lineNumber; type_ = type; } 167 168 LineNumber lineNumber() const 169 { return lineNumber_; } 170 FilteredLineType type() const 171 { return type_; } 172 173 private: 174 LineNumber lineNumber_; 175 FilteredLineType type_; 176 }; 177 178 #endif 179