xref: /glogg/src/main.cpp (revision 65076e2740cf0e36615f6cfde56f6e071ee170b9)
1 /*
2  * Copyright (C) 2009, 2010, 2011, 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 <QApplication>
21 
22 #include <memory>
23 
24 #include <boost/program_options.hpp>
25 namespace po = boost::program_options;
26 
27 #include <iostream>
28 #include <iomanip>
29 using namespace std;
30 
31 #ifdef _WIN32
32 #include "unistd.h"
33 #endif
34 
35 #include "persistentinfo.h"
36 #include "sessioninfo.h"
37 #include "configuration.h"
38 #include "filterset.h"
39 #include "recentfiles.h"
40 #include "session.h"
41 #include "mainwindow.h"
42 #include "savedsearches.h"
43 #include "loadingstatus.h"
44 
45 #include "externalcom.h"
46 #ifdef GLOGG_SUPPORTS_DBUS
47 #include "dbusexternalcom.h"
48 #elif GLOGG_SUPPORTS_WINIPC
49 #include "winexternalcom.h"
50 #endif
51 
52 
53 #include "log.h"
54 
55 static void print_version();
56 
57 int main(int argc, char *argv[])
58 {
59     QApplication app(argc, argv);
60 
61     string filename = "";
62 
63     // Configuration
64     bool new_session = false;
65     bool load_session = false;
66     bool multi_instance = false;
67 #ifdef _WIN32
68     bool log_to_file = false;
69 #endif
70 
71     TLogLevel logLevel = logWARNING;
72 
73     try {
74         po::options_description desc("Usage: glogg [options] [file]");
75         desc.add_options()
76             ("help,h", "print out program usage (this message)")
77             ("version,v", "print glogg's version information")
78             ("multi,m", "allow multiple instance of glogg to run simultaneously (use together with -s)")
79             ("load-session,s", "load the previous session (default when no file is passed)")
80             ("new-session,n", "do not load the previous session (default when a file is passed)")
81 #ifdef _WIN32
82             ("log,l", "save the log to a file (Windows only)")
83 #endif
84             ("debug,d", "output more debug (include multiple times for more verbosity e.g. -dddd)")
85             ;
86         po::options_description desc_hidden("Hidden options");
87         // For -dd, -ddd...
88         for ( string s = "dd"; s.length() <= 10; s.append("d") )
89             desc_hidden.add_options()(s.c_str(), "debug");
90 
91         desc_hidden.add_options()
92             ("input-file", po::value<string>(), "input file")
93             ;
94 
95         po::options_description all_options("all options");
96         all_options.add(desc).add(desc_hidden);
97 
98         po::positional_options_description positional;
99         positional.add("input-file", 1);
100 
101         int command_line_style = (((po::command_line_style::unix_style ^
102                 po::command_line_style::allow_guessing) |
103                 po::command_line_style::allow_long_disguise) ^
104                 po::command_line_style::allow_sticky);
105 
106         po::variables_map vm;
107         po::store(po::command_line_parser(argc, argv).
108                 options(all_options).
109                 positional(positional).
110                 style(command_line_style).run(),
111                 vm);
112         po::notify(vm);
113 
114         if ( vm.count("help") ) {
115             desc.print(cout);
116             return 0;
117         }
118 
119         if ( vm.count("version") ) {
120             print_version();
121             return 0;
122         }
123 
124         if ( vm.count( "debug" ) )
125             logLevel = logINFO;
126 
127         if ( vm.count( "multi" ) )
128             multi_instance = true;
129 
130         if ( vm.count( "new-session" ) )
131             new_session = true;
132 
133         if ( vm.count( "load-session" ) )
134             load_session = true;
135 
136 #ifdef _WIN32
137         if ( vm.count( "log" ) )
138             log_to_file = true;
139 #endif
140 
141         for ( string s = "dd"; s.length() <= 10; s.append("d") )
142             if ( vm.count( s ) )
143                 logLevel = (TLogLevel) (logWARNING + s.length());
144 
145         if ( vm.count("input-file") )
146             filename = vm["input-file"].as<string>();
147     }
148     catch(exception& e) {
149         cerr << "Option processing error: " << e.what() << endl;
150         return 1;
151     }
152     catch(...) {
153         cerr << "Exception of unknown type!\n";
154     }
155 
156 #ifdef _WIN32
157     if ( log_to_file )
158     {
159         char file_name[255];
160         snprintf( file_name, sizeof file_name, "glogg_%d.log", getpid() );
161         FILE* file = fopen(file_name, "w");
162         Output2FILE::Stream() = file;
163     }
164 #endif
165 
166     FILELog::setReportingLevel( logLevel );
167 
168     if ( ! filename.empty() ) {
169         // Convert to absolute path
170         QFileInfo file( QString::fromStdString( filename ) );
171         filename = file.absoluteFilePath().toStdString();
172     }
173 
174     // External communicator
175     shared_ptr<ExternalCommunicator> externalCommunicator = nullptr;
176     shared_ptr<ExternalInstance> externalInstance = nullptr;
177 
178     try {
179 #ifdef GLOGG_SUPPORTS_DBUS
180         externalCommunicator = make_shared<DBusExternalCommunicator>();
181         externalInstance = shared_ptr<ExternalInstance>(
182                 externalCommunicator->otherInstance() );
183 #elif GLOGG_SUPPORTS_WINIPC
184         externalCommunicator = make_shared<WinExternalCommunicator>();
185         externalInstance = shared_ptr<ExternalInstance>(
186                 externalCommunicator->otherInstance() );
187 #endif
188     }
189     catch(CantCreateExternalErr& e) {
190         LOG(logWARNING) << "Cannot initialise external communication.";
191     }
192 
193     LOG(logDEBUG) << "externalInstance = " << externalInstance;
194     if ( ( ! multi_instance ) && externalInstance ) {
195         uint32_t version = externalInstance->getVersion();
196         LOG(logINFO) << "Found another glogg (version = "
197             << std::setbase(16) << version << ")";
198 
199         externalInstance->loadFile( QString::fromStdString( filename ) );
200 
201         return 0;
202     }
203     else {
204         // FIXME: there is a race condition here. One glogg could start
205         // between the declaration of externalInstance and here,
206         // is it a problem?
207         if ( externalCommunicator )
208             externalCommunicator->startListening();
209     }
210 
211     // Register types for Qt
212     qRegisterMetaType<LoadingStatus>("LoadingStatus");
213 
214     // Register the configuration items
215     GetPersistentInfo().migrateAndInit();
216     GetPersistentInfo().registerPersistable(
217             std::make_shared<SessionInfo>(), QString( "session" ) );
218     GetPersistentInfo().registerPersistable(
219             std::make_shared<Configuration>(), QString( "settings" ) );
220     GetPersistentInfo().registerPersistable(
221             std::make_shared<FilterSet>(), QString( "filterSet" ) );
222     GetPersistentInfo().registerPersistable(
223             std::make_shared<SavedSearches>(), QString( "savedSearches" ) );
224     GetPersistentInfo().registerPersistable(
225             std::make_shared<RecentFiles>(), QString( "recentFiles" ) );
226 #ifdef GLOGG_SUPPORTS_VERSION_CHECKING
227     GetPersistentInfo().registerPersistable(
228             std::make_shared<VersionCheckerConfig>(), QString( "versionChecker" ) );
229 #endif
230 
231 #ifdef _WIN32
232     // Allow the app to raise it's own windows (in case an external
233     // glogg send us a file to open)
234     AllowSetForegroundWindow(ASFW_ANY);
235 #endif
236 
237     // FIXME: should be replaced by a two staged init of MainWindow
238     GetPersistentInfo().retrieve( QString( "settings" ) );
239 
240     std::unique_ptr<Session> session( new Session() );
241     MainWindow mw( std::move( session ), externalCommunicator );
242 
243     LOG(logDEBUG) << "MainWindow created.";
244     mw.show();
245     // Load the existing session if needed
246     if ( load_session || ( filename.empty() && !new_session ) )
247         mw.reloadSession();
248     mw.loadInitialFile( QString::fromStdString( filename ) );
249     mw.startBackgroundTasks();
250     return app.exec();
251 }
252 
253 static void print_version()
254 {
255     cout << "glogg " GLOGG_VERSION "\n";
256 #ifdef GLOGG_COMMIT
257     cout << "Built " GLOGG_DATE " from " GLOGG_COMMIT "\n";
258 #endif
259     cout << "Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Nicolas Bonnefon and other contributors\n";
260     cout << "This is free software.  You may redistribute copies of it under the terms of\n";
261     cout << "the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n";
262     cout << "There is NO WARRANTY, to the extent permitted by law.\n";
263 }
264