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