1 /*
2  * Copyright (C) 2013, 2014 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 #include "session.h"
21 
22 #include "log.h"
23 
24 #include <cassert>
25 #include <QFileInfo>
26 #include <algorithm>
27 
28 #include "viewinterface.h"
29 #include "persistentinfo.h"
30 #include "savedsearches.h"
31 #include "sessioninfo.h"
32 #include "data/logdata.h"
33 #include "data/logfiltereddata.h"
34 
Session()35 Session::Session()
36 {
37     GetPersistentInfo().retrieve( QString( "savedSearches" ) );
38 
39     // Get the global search history (it remains the property
40     // of the Persistent)
41     savedSearches_ = Persistent<SavedSearches>( "savedSearches" );
42 
43     quickFindPattern_ = std::make_shared<QuickFindPattern>();
44 }
45 
~Session()46 Session::~Session()
47 {
48     // FIXME Clean up all the data objects...
49 }
50 
getViewIfOpen(const std::string & file_name) const51 ViewInterface* Session::getViewIfOpen( const std::string& file_name ) const
52 {
53     auto result = std::find_if( openFiles_.begin(), openFiles_.end(),
54             [&](const std::pair<const ViewInterface*, OpenFile>& o)
55             { return ( o.second.fileName == file_name ); } );
56 
57     if ( result != openFiles_.end() )
58         return result->second.view;
59     else
60         return nullptr;
61 }
62 
open(const std::string & file_name,std::function<ViewInterface * ()> view_factory)63 ViewInterface* Session::open( const std::string& file_name,
64         std::function<ViewInterface*()> view_factory )
65 {
66     ViewInterface* view = nullptr;
67 
68     QFileInfo fileInfo( file_name.c_str() );
69     if ( fileInfo.isReadable() ) {
70         return openAlways( file_name, view_factory, nullptr );
71     }
72     else {
73         throw FileUnreadableErr();
74     }
75 
76     return view;
77 }
78 
close(const ViewInterface * view)79 void Session::close( const ViewInterface* view )
80 {
81     openFiles_.erase( openFiles_.find( view ) );
82 }
83 
save(std::vector<std::tuple<const ViewInterface *,uint64_t,std::shared_ptr<const ViewContextInterface>>> view_list,const QByteArray & geometry)84 void Session::save( std::vector<
85         std::tuple<const ViewInterface*,
86             uint64_t,
87             std::shared_ptr<const ViewContextInterface>>
88         > view_list,
89         const QByteArray& geometry )
90 {
91     LOG(logDEBUG) << "Session::save";
92 
93     std::vector<SessionInfo::OpenFile> session_files;
94     for ( auto view: view_list ) {
95         const ViewInterface* view_object;
96         uint64_t top_line;
97         std::shared_ptr<const ViewContextInterface> view_context;
98 
99         std::tie( view_object, top_line, view_context ) = view;
100 
101         const OpenFile* file = findOpenFileFromView( view_object );
102         assert( file );
103 
104         LOG(logDEBUG) << "Saving " << file->fileName << " in session.";
105         session_files.push_back( { file->fileName, top_line, view_context->toString() } );
106     }
107 
108     std::shared_ptr<SessionInfo> session =
109         Persistent<SessionInfo>( "session" );
110     session->setOpenFiles( session_files );
111     session->setGeometry( geometry );
112     GetPersistentInfo().save( QString( "session" ) );
113 }
114 
restore(std::function<ViewInterface * ()> view_factory,int * current_file_index)115 std::vector<std::pair<std::string, ViewInterface*>> Session::restore(
116         std::function<ViewInterface*()> view_factory,
117         int *current_file_index )
118 {
119     GetPersistentInfo().retrieve( QString( "session" ) );
120     std::shared_ptr<SessionInfo> session =
121         Persistent<SessionInfo>( "session" );
122 
123     std::vector<SessionInfo::OpenFile> session_files = session->openFiles();
124     LOG(logDEBUG) << "Session returned " << session_files.size();
125     std::vector<std::pair<std::string, ViewInterface*>> result;
126 
127     for ( auto file: session_files )
128     {
129         LOG(logDEBUG) << "Create view for " << file.fileName;
130         ViewInterface* view = openAlways( file.fileName, view_factory, file.viewContext.c_str() );
131         result.push_back( { file.fileName, view } );
132     }
133 
134     *current_file_index = -1;
135 
136     return result;
137 }
138 
storedGeometry(QByteArray * geometry) const139 void Session::storedGeometry( QByteArray* geometry ) const
140 {
141     GetPersistentInfo().retrieve( QString( "session" ) );
142     std::shared_ptr<SessionInfo> session =
143         Persistent<SessionInfo>( "session" );
144 
145     *geometry = session->geometry();
146 }
147 
getFilename(const ViewInterface * view) const148 std::string Session::getFilename( const ViewInterface* view ) const
149 {
150     const OpenFile* file = findOpenFileFromView( view );
151 
152     assert( file );
153 
154     return file->fileName;
155 }
156 
getFileInfo(const ViewInterface * view,uint64_t * fileSize,uint32_t * fileNbLine,QDateTime * lastModified) const157 void Session::getFileInfo( const ViewInterface* view, uint64_t* fileSize,
158         uint32_t* fileNbLine, QDateTime* lastModified ) const
159 {
160     const OpenFile* file = findOpenFileFromView( view );
161 
162     assert( file );
163 
164     *fileSize = file->logData->getFileSize();
165     *fileNbLine = file->logData->getNbLine();
166     *lastModified = file->logData->getLastModifiedDate();
167 }
168 
169 
170 /*
171  * Private methods
172  */
173 
openAlways(const std::string & file_name,std::function<ViewInterface * ()> view_factory,const char * view_context)174 ViewInterface* Session::openAlways( const std::string& file_name,
175         std::function<ViewInterface*()> view_factory,
176         const char* view_context )
177 {
178     // Create the data objects
179     auto log_data          = std::make_shared<LogData>();
180     auto log_filtered_data =
181         std::shared_ptr<LogFilteredData>( log_data->getNewFilteredData() );
182 
183     ViewInterface* view = view_factory();
184     view->setData( log_data, log_filtered_data );
185     view->setQuickFindPattern( quickFindPattern_ );
186     view->setSavedSearches( savedSearches_ );
187 
188     if ( view_context )
189         view->setViewContext( view_context );
190 
191     // Insert in the hash
192     openFiles_.insert( { view,
193             { file_name,
194             log_data,
195             log_filtered_data,
196             view } } );
197 
198     // Start loading the file
199     log_data->attachFile( QString( file_name.c_str() ) );
200 
201     return view;
202 }
203 
findOpenFileFromView(const ViewInterface * view)204 Session::OpenFile* Session::findOpenFileFromView( const ViewInterface* view )
205 {
206     assert( view );
207 
208     OpenFile* file = &( openFiles_.at( view ) );
209 
210     // OpenfileMap::at might throw out_of_range but since a view MUST always
211     // be attached to a file, we don't handle it!
212 
213     return file;
214 }
215 
findOpenFileFromView(const ViewInterface * view) const216 const Session::OpenFile* Session::findOpenFileFromView( const ViewInterface* view ) const
217 {
218     assert( view );
219 
220     const OpenFile* file = &( openFiles_.at( view ) );
221 
222     // OpenfileMap::at might throw out_of_range but since a view MUST always
223     // be attached to a file, we don't handle it!
224 
225     return file;
226 }
227