xref: /glogg/src/data/logdata.h (revision 84a8a910f1bab475f3fe7fe3fb12bd3690a2029a)
1bb02e0acSNicolas Bonnefon /*
2653377b6SNicolas Bonnefon  * Copyright (C) 2009, 2010, 2013, 2014, 2015 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 LOGDATA_H
21bb02e0acSNicolas Bonnefon #define LOGDATA_H
22bb02e0acSNicolas Bonnefon 
23306d9ac9SNicolas Bonnefon #include <memory>
24306d9ac9SNicolas Bonnefon 
25bb02e0acSNicolas Bonnefon #include <QObject>
26bb02e0acSNicolas Bonnefon #include <QString>
27bb02e0acSNicolas Bonnefon #include <QFile>
28bb02e0acSNicolas Bonnefon #include <QVector>
29bb02e0acSNicolas Bonnefon #include <QMutex>
30bb02e0acSNicolas Bonnefon #include <QDateTime>
315fa25391SNicolas Bonnefon #include <QTextCodec>
32bb02e0acSNicolas Bonnefon 
33dfb2a39cSNicolas Bonnefon #include "utils.h"
34dfb2a39cSNicolas Bonnefon 
35bb02e0acSNicolas Bonnefon #include "abstractlogdata.h"
36bb02e0acSNicolas Bonnefon #include "logdataworkerthread.h"
37bb02e0acSNicolas Bonnefon #include "filewatcher.h"
38812146a8SNicolas Bonnefon #include "loadingstatus.h"
39bb02e0acSNicolas Bonnefon 
40bb02e0acSNicolas Bonnefon class LogFilteredData;
41bb02e0acSNicolas Bonnefon 
421ee847caSNicolas Bonnefon // Thrown when trying to attach an already attached LogData
431ee847caSNicolas Bonnefon class CantReattachErr {};
441ee847caSNicolas Bonnefon 
45bb02e0acSNicolas Bonnefon // Represents a complete set of data to be displayed (ie. a log file content)
46bb02e0acSNicolas Bonnefon // This class is thread-safe.
47bb02e0acSNicolas Bonnefon class LogData : public AbstractLogData {
48bb02e0acSNicolas Bonnefon   Q_OBJECT
49bb02e0acSNicolas Bonnefon 
50bb02e0acSNicolas Bonnefon   public:
51bb02e0acSNicolas Bonnefon     // Creates an empty LogData
52bb02e0acSNicolas Bonnefon     LogData();
53bb02e0acSNicolas Bonnefon     // Destroy an object
54bb02e0acSNicolas Bonnefon     ~LogData();
55bb02e0acSNicolas Bonnefon 
56bb02e0acSNicolas Bonnefon     enum MonitoredFileStatus { Unchanged, DataAdded, Truncated };
57bb02e0acSNicolas Bonnefon 
581ee847caSNicolas Bonnefon     // Attaches the LogData to a file on disk
59bb02e0acSNicolas Bonnefon     // It starts the asynchronous indexing and returns (almost) immediately
60bb02e0acSNicolas Bonnefon     // Attaching to a non existant file works and the file is reported
61bb02e0acSNicolas Bonnefon     // to be empty.
621ee847caSNicolas Bonnefon     // Reattaching is forbidden and will throw.
63bb02e0acSNicolas Bonnefon     void attachFile( const QString& fileName );
641ee847caSNicolas Bonnefon     // Interrupt the loading and report a null file.
65bb02e0acSNicolas Bonnefon     // Does nothing if no loading in progress.
66bb02e0acSNicolas Bonnefon     void interruptLoading();
671ee847caSNicolas Bonnefon     // Creates a new filtered data.
68bb02e0acSNicolas Bonnefon     // ownership is passed to the caller
69bb02e0acSNicolas Bonnefon     LogFilteredData* getNewFilteredData() const;
70bb02e0acSNicolas Bonnefon     // Returns the size if the file in bytes
71bb02e0acSNicolas Bonnefon     qint64 getFileSize() const;
72bb02e0acSNicolas Bonnefon     // Returns the last modification date for the file.
73bb02e0acSNicolas Bonnefon     // Null if the file is not on disk.
74bb02e0acSNicolas Bonnefon     QDateTime getLastModifiedDate() const;
7532e44cfdSNicolas Bonnefon     // Throw away all the file data and reload/reindex.
7632e44cfdSNicolas Bonnefon     void reload();
77bb02e0acSNicolas Bonnefon 
7880bca0a3SNicolas Bonnefon     // Update the polling interval (in ms, 0 means disabled)
7980bca0a3SNicolas Bonnefon     void setPollingInterval( uint32_t interval_ms );
8080bca0a3SNicolas Bonnefon 
815fa25391SNicolas Bonnefon     // Get the auto-detected encoding for the indexed text.
825fa25391SNicolas Bonnefon     EncodingSpeculator::Encoding getDetectedEncoding() const;
835fa25391SNicolas Bonnefon 
84bb02e0acSNicolas Bonnefon   signals:
85bb02e0acSNicolas Bonnefon     // Sent during the 'attach' process to signal progress
86bb02e0acSNicolas Bonnefon     // percent being the percentage of completion.
87bb02e0acSNicolas Bonnefon     void loadingProgressed( int percent );
88bb02e0acSNicolas Bonnefon     // Signal the client the file is fully loaded and available.
89812146a8SNicolas Bonnefon     void loadingFinished( LoadingStatus status );
90bb02e0acSNicolas Bonnefon     // Sent when the file on disk has changed, will be followed
91bb02e0acSNicolas Bonnefon     // by loadingProgressed if needed and then a loadingFinished.
92bb02e0acSNicolas Bonnefon     void fileChanged( LogData::MonitoredFileStatus status );
93bb02e0acSNicolas Bonnefon 
94bb02e0acSNicolas Bonnefon   private slots:
95bb02e0acSNicolas Bonnefon     // Consider reloading the file when it changes on disk updated
96bb02e0acSNicolas Bonnefon     void fileChangedOnDisk();
97bb02e0acSNicolas Bonnefon     // Called when the worker thread signals the current operation ended
98812146a8SNicolas Bonnefon     void indexingFinished( LoadingStatus status );
99bb02e0acSNicolas Bonnefon 
100bb02e0acSNicolas Bonnefon   private:
101bb02e0acSNicolas Bonnefon     // This class models an indexing operation.
102bb02e0acSNicolas Bonnefon     // It exists to permit LogData to delay the operation if another
103bb02e0acSNicolas Bonnefon     // one is ongoing (operations are asynchronous)
104bb02e0acSNicolas Bonnefon     class LogDataOperation {
105bb02e0acSNicolas Bonnefon       public:
LogDataOperation(const QString & fileName)106bb02e0acSNicolas Bonnefon         LogDataOperation( const QString& fileName ) : filename_( fileName ) {}
107bb02e0acSNicolas Bonnefon         // Permit each child to have its destructor
~LogDataOperation()108bb02e0acSNicolas Bonnefon         virtual ~LogDataOperation() {};
109bb02e0acSNicolas Bonnefon 
start(LogDataWorkerThread & workerThread)110bb02e0acSNicolas Bonnefon         void start( LogDataWorkerThread& workerThread ) const
111bb02e0acSNicolas Bonnefon         { doStart( workerThread ); }
getFilename()112bb02e0acSNicolas Bonnefon         const QString& getFilename() const { return filename_; }
113bb02e0acSNicolas Bonnefon 
114bb02e0acSNicolas Bonnefon       protected:
115bb02e0acSNicolas Bonnefon         virtual void doStart( LogDataWorkerThread& workerThread ) const = 0;
116bb02e0acSNicolas Bonnefon         QString filename_;
117bb02e0acSNicolas Bonnefon     };
118bb02e0acSNicolas Bonnefon 
119bb02e0acSNicolas Bonnefon     // Attaching a new file (change name + full index)
120bb02e0acSNicolas Bonnefon     class AttachOperation : public LogDataOperation {
121bb02e0acSNicolas Bonnefon       public:
AttachOperation(const QString & fileName)122bb02e0acSNicolas Bonnefon         AttachOperation( const QString& fileName )
123bb02e0acSNicolas Bonnefon             : LogDataOperation( fileName ) {}
~AttachOperation()124bb02e0acSNicolas Bonnefon         ~AttachOperation() {};
125bb02e0acSNicolas Bonnefon 
126bb02e0acSNicolas Bonnefon       protected:
127bb02e0acSNicolas Bonnefon         void doStart( LogDataWorkerThread& workerThread ) const;
128bb02e0acSNicolas Bonnefon     };
129bb02e0acSNicolas Bonnefon 
130bb02e0acSNicolas Bonnefon     // Reindexing the current file
131bb02e0acSNicolas Bonnefon     class FullIndexOperation : public LogDataOperation {
132bb02e0acSNicolas Bonnefon       public:
FullIndexOperation()133bb02e0acSNicolas Bonnefon         FullIndexOperation() : LogDataOperation( QString() ) {}
~FullIndexOperation()134bb02e0acSNicolas Bonnefon         ~FullIndexOperation() {};
135bb02e0acSNicolas Bonnefon 
136bb02e0acSNicolas Bonnefon       protected:
137bb02e0acSNicolas Bonnefon         void doStart( LogDataWorkerThread& workerThread ) const;
138bb02e0acSNicolas Bonnefon     };
139bb02e0acSNicolas Bonnefon 
140bb02e0acSNicolas Bonnefon     // Indexing part of the current file (from fileSize)
141bb02e0acSNicolas Bonnefon     class PartialIndexOperation : public LogDataOperation {
142bb02e0acSNicolas Bonnefon       public:
PartialIndexOperation()143de1abac6SNicolas Bonnefon         PartialIndexOperation() : LogDataOperation( QString() ) {}
~PartialIndexOperation()144bb02e0acSNicolas Bonnefon         ~PartialIndexOperation() {};
145bb02e0acSNicolas Bonnefon 
146bb02e0acSNicolas Bonnefon       protected:
147bb02e0acSNicolas Bonnefon         void doStart( LogDataWorkerThread& workerThread ) const;
148bb02e0acSNicolas Bonnefon     };
149bb02e0acSNicolas Bonnefon 
1506a12446eSNicolas Bonnefon     std::shared_ptr<FileWatcher> fileWatcher_;
151bb02e0acSNicolas Bonnefon     MonitoredFileStatus fileChangedOnDisk_;
152bb02e0acSNicolas Bonnefon 
153bb02e0acSNicolas Bonnefon     // Implementation of virtual functions
1541ee847caSNicolas Bonnefon     QString doGetLineString( qint64 line ) const override;
1551ee847caSNicolas Bonnefon     QString doGetExpandedLineString( qint64 line ) const override;
1561ee847caSNicolas Bonnefon     QStringList doGetLines( qint64 first, int number ) const override;
1571ee847caSNicolas Bonnefon     QStringList doGetExpandedLines( qint64 first, int number ) const override;
1581ee847caSNicolas Bonnefon     qint64 doGetNbLine() const override;
1591ee847caSNicolas Bonnefon     int doGetMaxLength() const override;
1601ee847caSNicolas Bonnefon     int doGetLineLength( qint64 line ) const override;
161209000a6SNicolas Bonnefon     void doSetDisplayEncoding( Encoding encoding ) override;
1624a4a124eSNicolas Bonnefon     void doSetMultibyteEncodingOffsets( int before_cr, int after_cr ) override;
163bb02e0acSNicolas Bonnefon 
164306d9ac9SNicolas Bonnefon     void enqueueOperation( std::shared_ptr<const LogDataOperation> newOperation );
165bb02e0acSNicolas Bonnefon     void startOperation();
166*84a8a910SNicolas Bonnefon     void reOpenFile();
167bb02e0acSNicolas Bonnefon 
168209000a6SNicolas Bonnefon     qint64 endOfLinePosition( qint64 line ) const;
169209000a6SNicolas Bonnefon     qint64 beginningOfNextLine( qint64 end_pos ) const;
170209000a6SNicolas Bonnefon 
171bb02e0acSNicolas Bonnefon     QString indexingFileName_;
1721ee847caSNicolas Bonnefon     std::unique_ptr<QFile> attached_file_;
173653377b6SNicolas Bonnefon 
174653377b6SNicolas Bonnefon     // Indexing data, read by us, written by the worker thread
175653377b6SNicolas Bonnefon     IndexingData indexing_data_;
176653377b6SNicolas Bonnefon 
177bb02e0acSNicolas Bonnefon     QDateTime lastModifiedDate_;
178306d9ac9SNicolas Bonnefon     std::shared_ptr<const LogDataOperation> currentOperation_;
179306d9ac9SNicolas Bonnefon     std::shared_ptr<const LogDataOperation> nextOperation_;
180bb02e0acSNicolas Bonnefon 
1815fa25391SNicolas Bonnefon     // Codec to decode text
1825fa25391SNicolas Bonnefon     QTextCodec* codec_;
1835fa25391SNicolas Bonnefon 
1844a4a124eSNicolas Bonnefon     // Offset to apply to the newline character
1854a4a124eSNicolas Bonnefon     int before_cr_offset_ = 0;
1864a4a124eSNicolas Bonnefon     int after_cr_offset_  = 0;
1874a4a124eSNicolas Bonnefon 
188bb02e0acSNicolas Bonnefon     // To protect the file:
189bb02e0acSNicolas Bonnefon     mutable QMutex fileMutex_;
190bb02e0acSNicolas Bonnefon     // (are mutable to allow 'const' function to touch it,
191bb02e0acSNicolas Bonnefon     // while remaining const)
192bb02e0acSNicolas Bonnefon     // When acquiring both, data should be help before locking file.
193bb02e0acSNicolas Bonnefon 
194bb02e0acSNicolas Bonnefon     LogDataWorkerThread workerThread_;
195bb02e0acSNicolas Bonnefon };
196bb02e0acSNicolas Bonnefon 
1971ee847caSNicolas Bonnefon Q_DECLARE_METATYPE( LogData::MonitoredFileStatus );
1981ee847caSNicolas Bonnefon 
199bb02e0acSNicolas Bonnefon #endif
200