xref: /glogg/src/main.cpp (revision 4752846b40986d3211465f1f88cc119d69b55bd1)
1bb02e0acSNicolas Bonnefon /*
2812146a8SNicolas Bonnefon  * Copyright (C) 2009, 2010, 2011, 2013, 2014 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 #include <QApplication>
21*4752846bSNicolas Bonnefon #include <QFileInfo>
22bb02e0acSNicolas Bonnefon 
23d96f3f21SNicolas Bonnefon #include <memory>
24d96f3f21SNicolas Bonnefon 
25bb02e0acSNicolas Bonnefon #include <boost/program_options.hpp>
26bb02e0acSNicolas Bonnefon namespace po = boost::program_options;
27bb02e0acSNicolas Bonnefon 
28bb02e0acSNicolas Bonnefon #include <iostream>
29e07da50aSNicolas Bonnefon #include <iomanip>
30bb02e0acSNicolas Bonnefon using namespace std;
31bb02e0acSNicolas Bonnefon 
32320f9110SNicolas Bonnefon #ifdef _WIN32
33320f9110SNicolas Bonnefon #include "unistd.h"
34320f9110SNicolas Bonnefon #endif
35320f9110SNicolas Bonnefon 
36bb02e0acSNicolas Bonnefon #include "persistentinfo.h"
37bb02e0acSNicolas Bonnefon #include "sessioninfo.h"
38bb02e0acSNicolas Bonnefon #include "configuration.h"
39bb02e0acSNicolas Bonnefon #include "filterset.h"
40bb02e0acSNicolas Bonnefon #include "recentfiles.h"
41d96f3f21SNicolas Bonnefon #include "session.h"
42bb02e0acSNicolas Bonnefon #include "mainwindow.h"
43bb02e0acSNicolas Bonnefon #include "savedsearches.h"
44812146a8SNicolas Bonnefon #include "loadingstatus.h"
4515af0893SNicolas Bonnefon 
4615af0893SNicolas Bonnefon #include "externalcom.h"
4715af0893SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_DBUS
48557fb9d8SNicolas Bonnefon #include "dbusexternalcom.h"
4924895119SNicolas Bonnefon #elif GLOGG_SUPPORTS_WINIPC
5024895119SNicolas Bonnefon #include "winexternalcom.h"
5115af0893SNicolas Bonnefon #endif
5215af0893SNicolas Bonnefon 
5324895119SNicolas Bonnefon 
54bb02e0acSNicolas Bonnefon #include "log.h"
55bb02e0acSNicolas Bonnefon 
56bb02e0acSNicolas Bonnefon static void print_version();
57bb02e0acSNicolas Bonnefon 
58bb02e0acSNicolas Bonnefon int main(int argc, char *argv[])
59bb02e0acSNicolas Bonnefon {
60bb02e0acSNicolas Bonnefon     QApplication app(argc, argv);
61bb02e0acSNicolas Bonnefon 
62bb02e0acSNicolas Bonnefon     string filename = "";
63bb02e0acSNicolas Bonnefon 
64da4beab3SNicolas Bonnefon     // Configuration
65da4beab3SNicolas Bonnefon     bool new_session = false;
661e522573SNicolas Bonnefon     bool load_session = false;
67da4beab3SNicolas Bonnefon     bool multi_instance = false;
68320f9110SNicolas Bonnefon #ifdef _WIN32
69320f9110SNicolas Bonnefon     bool log_to_file = false;
70320f9110SNicolas Bonnefon #endif
71da4beab3SNicolas Bonnefon 
72bb02e0acSNicolas Bonnefon     TLogLevel logLevel = logWARNING;
73bb02e0acSNicolas Bonnefon 
74bb02e0acSNicolas Bonnefon     try {
75bb02e0acSNicolas Bonnefon         po::options_description desc("Usage: glogg [options] [file]");
76bb02e0acSNicolas Bonnefon         desc.add_options()
77bb02e0acSNicolas Bonnefon             ("help,h", "print out program usage (this message)")
78bb02e0acSNicolas Bonnefon             ("version,v", "print glogg's version information")
79da4beab3SNicolas Bonnefon             ("multi,m", "allow multiple instance of glogg to run simultaneously (use together with -s)")
801e522573SNicolas Bonnefon             ("load-session,s", "load the previous session (default when no file is passed)")
811e522573SNicolas Bonnefon             ("new-session,n", "do not load the previous session (default when a file is passed)")
82320f9110SNicolas Bonnefon #ifdef _WIN32
83320f9110SNicolas Bonnefon             ("log,l", "save the log to a file (Windows only)")
84320f9110SNicolas Bonnefon #endif
851e522573SNicolas Bonnefon             ("debug,d", "output more debug (include multiple times for more verbosity e.g. -dddd)")
86bb02e0acSNicolas Bonnefon             ;
87bb02e0acSNicolas Bonnefon         po::options_description desc_hidden("Hidden options");
88bb02e0acSNicolas Bonnefon         // For -dd, -ddd...
89bb02e0acSNicolas Bonnefon         for ( string s = "dd"; s.length() <= 10; s.append("d") )
90bb02e0acSNicolas Bonnefon             desc_hidden.add_options()(s.c_str(), "debug");
91bb02e0acSNicolas Bonnefon 
92bb02e0acSNicolas Bonnefon         desc_hidden.add_options()
93bb02e0acSNicolas Bonnefon             ("input-file", po::value<string>(), "input file")
94bb02e0acSNicolas Bonnefon             ;
95bb02e0acSNicolas Bonnefon 
96bb02e0acSNicolas Bonnefon         po::options_description all_options("all options");
97bb02e0acSNicolas Bonnefon         all_options.add(desc).add(desc_hidden);
98bb02e0acSNicolas Bonnefon 
99bb02e0acSNicolas Bonnefon         po::positional_options_description positional;
100bb02e0acSNicolas Bonnefon         positional.add("input-file", 1);
101bb02e0acSNicolas Bonnefon 
102bb02e0acSNicolas Bonnefon         int command_line_style = (((po::command_line_style::unix_style ^
103bb02e0acSNicolas Bonnefon                 po::command_line_style::allow_guessing) |
104bb02e0acSNicolas Bonnefon                 po::command_line_style::allow_long_disguise) ^
105bb02e0acSNicolas Bonnefon                 po::command_line_style::allow_sticky);
106bb02e0acSNicolas Bonnefon 
107bb02e0acSNicolas Bonnefon         po::variables_map vm;
108bb02e0acSNicolas Bonnefon         po::store(po::command_line_parser(argc, argv).
109bb02e0acSNicolas Bonnefon                 options(all_options).
110bb02e0acSNicolas Bonnefon                 positional(positional).
111bb02e0acSNicolas Bonnefon                 style(command_line_style).run(),
112bb02e0acSNicolas Bonnefon                 vm);
113bb02e0acSNicolas Bonnefon         po::notify(vm);
114bb02e0acSNicolas Bonnefon 
115bb02e0acSNicolas Bonnefon         if ( vm.count("help") ) {
116bb02e0acSNicolas Bonnefon             desc.print(cout);
117bb02e0acSNicolas Bonnefon             return 0;
118bb02e0acSNicolas Bonnefon         }
119bb02e0acSNicolas Bonnefon 
120bb02e0acSNicolas Bonnefon         if ( vm.count("version") ) {
121bb02e0acSNicolas Bonnefon             print_version();
122bb02e0acSNicolas Bonnefon             return 0;
123bb02e0acSNicolas Bonnefon         }
124bb02e0acSNicolas Bonnefon 
125da4beab3SNicolas Bonnefon         if ( vm.count( "debug" ) )
126bb02e0acSNicolas Bonnefon             logLevel = logINFO;
127da4beab3SNicolas Bonnefon 
128da4beab3SNicolas Bonnefon         if ( vm.count( "multi" ) )
129da4beab3SNicolas Bonnefon             multi_instance = true;
130da4beab3SNicolas Bonnefon 
131da4beab3SNicolas Bonnefon         if ( vm.count( "new-session" ) )
132da4beab3SNicolas Bonnefon             new_session = true;
133bb02e0acSNicolas Bonnefon 
1341e522573SNicolas Bonnefon         if ( vm.count( "load-session" ) )
1351e522573SNicolas Bonnefon             load_session = true;
1361e522573SNicolas Bonnefon 
137320f9110SNicolas Bonnefon #ifdef _WIN32
138320f9110SNicolas Bonnefon         if ( vm.count( "log" ) )
139320f9110SNicolas Bonnefon             log_to_file = true;
140320f9110SNicolas Bonnefon #endif
141320f9110SNicolas Bonnefon 
142bb02e0acSNicolas Bonnefon         for ( string s = "dd"; s.length() <= 10; s.append("d") )
143bb02e0acSNicolas Bonnefon             if ( vm.count( s ) )
144bb02e0acSNicolas Bonnefon                 logLevel = (TLogLevel) (logWARNING + s.length());
145bb02e0acSNicolas Bonnefon 
146bb02e0acSNicolas Bonnefon         if ( vm.count("input-file") )
147bb02e0acSNicolas Bonnefon             filename = vm["input-file"].as<string>();
148bb02e0acSNicolas Bonnefon     }
149bb02e0acSNicolas Bonnefon     catch(exception& e) {
150bb02e0acSNicolas Bonnefon         cerr << "Option processing error: " << e.what() << endl;
151bb02e0acSNicolas Bonnefon         return 1;
152bb02e0acSNicolas Bonnefon     }
153bb02e0acSNicolas Bonnefon     catch(...) {
154bb02e0acSNicolas Bonnefon         cerr << "Exception of unknown type!\n";
155bb02e0acSNicolas Bonnefon     }
156bb02e0acSNicolas Bonnefon 
157320f9110SNicolas Bonnefon #ifdef _WIN32
158320f9110SNicolas Bonnefon     if ( log_to_file )
159320f9110SNicolas Bonnefon     {
160320f9110SNicolas Bonnefon         char file_name[255];
161320f9110SNicolas Bonnefon         snprintf( file_name, sizeof file_name, "glogg_%d.log", getpid() );
162320f9110SNicolas Bonnefon         FILE* file = fopen(file_name, "w");
163bb02e0acSNicolas Bonnefon         Output2FILE::Stream() = file;
164320f9110SNicolas Bonnefon     }
165bb02e0acSNicolas Bonnefon #endif
166bb02e0acSNicolas Bonnefon 
167bb02e0acSNicolas Bonnefon     FILELog::setReportingLevel( logLevel );
168bb02e0acSNicolas Bonnefon 
16965076e27SNicolas Bonnefon     if ( ! filename.empty() ) {
17065076e27SNicolas Bonnefon         // Convert to absolute path
17165076e27SNicolas Bonnefon         QFileInfo file( QString::fromStdString( filename ) );
17265076e27SNicolas Bonnefon         filename = file.absoluteFilePath().toStdString();
17365076e27SNicolas Bonnefon     }
17465076e27SNicolas Bonnefon 
175e07da50aSNicolas Bonnefon     // External communicator
176da4beab3SNicolas Bonnefon     shared_ptr<ExternalCommunicator> externalCommunicator = nullptr;
177da4beab3SNicolas Bonnefon     shared_ptr<ExternalInstance> externalInstance = nullptr;
178da4beab3SNicolas Bonnefon 
179da4beab3SNicolas Bonnefon     try {
18015af0893SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_DBUS
181da4beab3SNicolas Bonnefon         externalCommunicator = make_shared<DBusExternalCommunicator>();
182da4beab3SNicolas Bonnefon         externalInstance = shared_ptr<ExternalInstance>(
183da4beab3SNicolas Bonnefon                 externalCommunicator->otherInstance() );
18424895119SNicolas Bonnefon #elif GLOGG_SUPPORTS_WINIPC
18524895119SNicolas Bonnefon         externalCommunicator = make_shared<WinExternalCommunicator>();
18624895119SNicolas Bonnefon         externalInstance = shared_ptr<ExternalInstance>(
18724895119SNicolas Bonnefon                 externalCommunicator->otherInstance() );
18815af0893SNicolas Bonnefon #endif
189da4beab3SNicolas Bonnefon     }
190da4beab3SNicolas Bonnefon     catch(CantCreateExternalErr& e) {
191da4beab3SNicolas Bonnefon         LOG(logWARNING) << "Cannot initialise external communication.";
192da4beab3SNicolas Bonnefon     }
193557fb9d8SNicolas Bonnefon 
194e07da50aSNicolas Bonnefon     LOG(logDEBUG) << "externalInstance = " << externalInstance;
195da4beab3SNicolas Bonnefon     if ( ( ! multi_instance ) && externalInstance ) {
196e07da50aSNicolas Bonnefon         uint32_t version = externalInstance->getVersion();
197e07da50aSNicolas Bonnefon         LOG(logINFO) << "Found another glogg (version = "
198e07da50aSNicolas Bonnefon             << std::setbase(16) << version << ")";
199e07da50aSNicolas Bonnefon 
20009aff35dSNicolas Bonnefon         externalInstance->loadFile( QString::fromStdString( filename ) );
20109aff35dSNicolas Bonnefon 
202e07da50aSNicolas Bonnefon         return 0;
203e07da50aSNicolas Bonnefon     }
204e07da50aSNicolas Bonnefon     else {
205e07da50aSNicolas Bonnefon         // FIXME: there is a race condition here. One glogg could start
206e07da50aSNicolas Bonnefon         // between the declaration of externalInstance and here,
207e07da50aSNicolas Bonnefon         // is it a problem?
208da4beab3SNicolas Bonnefon         if ( externalCommunicator )
209e07da50aSNicolas Bonnefon             externalCommunicator->startListening();
210e07da50aSNicolas Bonnefon     }
211e07da50aSNicolas Bonnefon 
212812146a8SNicolas Bonnefon     // Register types for Qt
213812146a8SNicolas Bonnefon     qRegisterMetaType<LoadingStatus>("LoadingStatus");
214812146a8SNicolas Bonnefon 
215bb02e0acSNicolas Bonnefon     // Register the configuration items
216bb02e0acSNicolas Bonnefon     GetPersistentInfo().migrateAndInit();
217bb02e0acSNicolas Bonnefon     GetPersistentInfo().registerPersistable(
21811582726SNicolas Bonnefon             std::make_shared<SessionInfo>(), QString( "session" ) );
219bb02e0acSNicolas Bonnefon     GetPersistentInfo().registerPersistable(
22011582726SNicolas Bonnefon             std::make_shared<Configuration>(), QString( "settings" ) );
221bb02e0acSNicolas Bonnefon     GetPersistentInfo().registerPersistable(
22211582726SNicolas Bonnefon             std::make_shared<FilterSet>(), QString( "filterSet" ) );
223bb02e0acSNicolas Bonnefon     GetPersistentInfo().registerPersistable(
22411582726SNicolas Bonnefon             std::make_shared<SavedSearches>(), QString( "savedSearches" ) );
225bb02e0acSNicolas Bonnefon     GetPersistentInfo().registerPersistable(
22611582726SNicolas Bonnefon             std::make_shared<RecentFiles>(), QString( "recentFiles" ) );
227a3f81147SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_VERSION_CHECKING
228a3f81147SNicolas Bonnefon     GetPersistentInfo().registerPersistable(
229a3f81147SNicolas Bonnefon             std::make_shared<VersionCheckerConfig>(), QString( "versionChecker" ) );
230a3f81147SNicolas Bonnefon #endif
231bb02e0acSNicolas Bonnefon 
232cf609627SNicolas Bonnefon #ifdef _WIN32
233cf609627SNicolas Bonnefon     // Allow the app to raise it's own windows (in case an external
234cf609627SNicolas Bonnefon     // glogg send us a file to open)
235cf609627SNicolas Bonnefon     AllowSetForegroundWindow(ASFW_ANY);
236cf609627SNicolas Bonnefon #endif
237cf609627SNicolas Bonnefon 
238bb02e0acSNicolas Bonnefon     // FIXME: should be replaced by a two staged init of MainWindow
239bb02e0acSNicolas Bonnefon     GetPersistentInfo().retrieve( QString( "settings" ) );
240bb02e0acSNicolas Bonnefon 
241d96f3f21SNicolas Bonnefon     std::unique_ptr<Session> session( new Session() );
24209aff35dSNicolas Bonnefon     MainWindow mw( std::move( session ), externalCommunicator );
243bb02e0acSNicolas Bonnefon 
244bb02e0acSNicolas Bonnefon     LOG(logDEBUG) << "MainWindow created.";
2450f9fd9edSNicolas Bonnefon     mw.show();
2461e522573SNicolas Bonnefon     // Load the existing session if needed
2471e522573SNicolas Bonnefon     if ( load_session || ( filename.empty() && !new_session ) )
2480f9fd9edSNicolas Bonnefon         mw.reloadSession();
2490f9fd9edSNicolas Bonnefon     mw.loadInitialFile( QString::fromStdString( filename ) );
2508a9275b2SNicolas Bonnefon     mw.startBackgroundTasks();
251bb02e0acSNicolas Bonnefon     return app.exec();
252bb02e0acSNicolas Bonnefon }
253bb02e0acSNicolas Bonnefon 
254bb02e0acSNicolas Bonnefon static void print_version()
255bb02e0acSNicolas Bonnefon {
256bb02e0acSNicolas Bonnefon     cout << "glogg " GLOGG_VERSION "\n";
257bb02e0acSNicolas Bonnefon #ifdef GLOGG_COMMIT
258bb02e0acSNicolas Bonnefon     cout << "Built " GLOGG_DATE " from " GLOGG_COMMIT "\n";
259bb02e0acSNicolas Bonnefon #endif
2608a9275b2SNicolas Bonnefon     cout << "Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Nicolas Bonnefon and other contributors\n";
261bb02e0acSNicolas Bonnefon     cout << "This is free software.  You may redistribute copies of it under the terms of\n";
262bb02e0acSNicolas Bonnefon     cout << "the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n";
263bb02e0acSNicolas Bonnefon     cout << "There is NO WARRANTY, to the extent permitted by law.\n";
264bb02e0acSNicolas Bonnefon }
265