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