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