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
204752846bSNicolas Bonnefon #include <QFileInfo>
21bb02e0acSNicolas Bonnefon
22d96f3f21SNicolas Bonnefon #include <memory>
23d96f3f21SNicolas Bonnefon
24bb02e0acSNicolas Bonnefon #include <boost/program_options.hpp>
25bb02e0acSNicolas Bonnefon namespace po = boost::program_options;
26bb02e0acSNicolas Bonnefon
27bb02e0acSNicolas Bonnefon #include <iostream>
28e07da50aSNicolas Bonnefon #include <iomanip>
29bb02e0acSNicolas Bonnefon using namespace std;
30bb02e0acSNicolas Bonnefon
31320f9110SNicolas Bonnefon #ifdef _WIN32
32320f9110SNicolas Bonnefon #include "unistd.h"
33320f9110SNicolas Bonnefon #endif
34320f9110SNicolas Bonnefon
35*ba1adacfSNicolas Bonnefon #include "gloggapp.h"
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"
470374f408SAnton Filimonov
4815af0893SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_DBUS
49557fb9d8SNicolas Bonnefon #include "dbusexternalcom.h"
502d1bee56SNicolas Bonnefon #elif GLOGG_SUPPORTS_SOCKETIPC
510374f408SAnton Filimonov #include "socketexternalcom.h"
5215af0893SNicolas Bonnefon #endif
5315af0893SNicolas Bonnefon
5424895119SNicolas Bonnefon
55bb02e0acSNicolas Bonnefon #include "log.h"
56bb02e0acSNicolas Bonnefon
57bb02e0acSNicolas Bonnefon static void print_version();
58bb02e0acSNicolas Bonnefon
main(int argc,char * argv[])59bb02e0acSNicolas Bonnefon int main(int argc, char *argv[])
60bb02e0acSNicolas Bonnefon {
61*ba1adacfSNicolas Bonnefon GloggApp app(argc, argv);
62bb02e0acSNicolas Bonnefon
631311017aSAnton Filimonov vector<string> filenames;
64bb02e0acSNicolas Bonnefon
65da4beab3SNicolas Bonnefon // Configuration
66da4beab3SNicolas Bonnefon bool new_session = false;
671e522573SNicolas Bonnefon bool load_session = false;
68da4beab3SNicolas Bonnefon bool multi_instance = false;
69320f9110SNicolas Bonnefon #ifdef _WIN32
70320f9110SNicolas Bonnefon bool log_to_file = false;
71320f9110SNicolas Bonnefon #endif
72da4beab3SNicolas Bonnefon
73bb02e0acSNicolas Bonnefon TLogLevel logLevel = logWARNING;
74bb02e0acSNicolas Bonnefon
75bb02e0acSNicolas Bonnefon try {
7690d2843cSNicolas Bonnefon po::options_description desc("Usage: glogg [options] [files]");
77bb02e0acSNicolas Bonnefon desc.add_options()
78bb02e0acSNicolas Bonnefon ("help,h", "print out program usage (this message)")
79bb02e0acSNicolas Bonnefon ("version,v", "print glogg's version information")
80da4beab3SNicolas Bonnefon ("multi,m", "allow multiple instance of glogg to run simultaneously (use together with -s)")
811e522573SNicolas Bonnefon ("load-session,s", "load the previous session (default when no file is passed)")
821e522573SNicolas Bonnefon ("new-session,n", "do not load the previous session (default when a file is passed)")
83320f9110SNicolas Bonnefon #ifdef _WIN32
84320f9110SNicolas Bonnefon ("log,l", "save the log to a file (Windows only)")
85320f9110SNicolas Bonnefon #endif
861e522573SNicolas Bonnefon ("debug,d", "output more debug (include multiple times for more verbosity e.g. -dddd)")
87bb02e0acSNicolas Bonnefon ;
88bb02e0acSNicolas Bonnefon po::options_description desc_hidden("Hidden options");
89bb02e0acSNicolas Bonnefon // For -dd, -ddd...
90bb02e0acSNicolas Bonnefon for ( string s = "dd"; s.length() <= 10; s.append("d") )
91bb02e0acSNicolas Bonnefon desc_hidden.add_options()(s.c_str(), "debug");
92bb02e0acSNicolas Bonnefon
93bb02e0acSNicolas Bonnefon desc_hidden.add_options()
941311017aSAnton Filimonov ("input-file", po::value<vector<string>>(), "input file")
95bb02e0acSNicolas Bonnefon ;
96bb02e0acSNicolas Bonnefon
97bb02e0acSNicolas Bonnefon po::options_description all_options("all options");
98bb02e0acSNicolas Bonnefon all_options.add(desc).add(desc_hidden);
99bb02e0acSNicolas Bonnefon
100bb02e0acSNicolas Bonnefon po::positional_options_description positional;
1011311017aSAnton Filimonov positional.add("input-file", -1);
102bb02e0acSNicolas Bonnefon
103bb02e0acSNicolas Bonnefon int command_line_style = (((po::command_line_style::unix_style ^
104bb02e0acSNicolas Bonnefon po::command_line_style::allow_guessing) |
105bb02e0acSNicolas Bonnefon po::command_line_style::allow_long_disguise) ^
106bb02e0acSNicolas Bonnefon po::command_line_style::allow_sticky);
107bb02e0acSNicolas Bonnefon
108bb02e0acSNicolas Bonnefon po::variables_map vm;
109bb02e0acSNicolas Bonnefon po::store(po::command_line_parser(argc, argv).
110bb02e0acSNicolas Bonnefon options(all_options).
111bb02e0acSNicolas Bonnefon positional(positional).
112bb02e0acSNicolas Bonnefon style(command_line_style).run(),
113bb02e0acSNicolas Bonnefon vm);
114bb02e0acSNicolas Bonnefon po::notify(vm);
115bb02e0acSNicolas Bonnefon
116bb02e0acSNicolas Bonnefon if ( vm.count("help") ) {
117bb02e0acSNicolas Bonnefon desc.print(cout);
118bb02e0acSNicolas Bonnefon return 0;
119bb02e0acSNicolas Bonnefon }
120bb02e0acSNicolas Bonnefon
121bb02e0acSNicolas Bonnefon if ( vm.count("version") ) {
122bb02e0acSNicolas Bonnefon print_version();
123bb02e0acSNicolas Bonnefon return 0;
124bb02e0acSNicolas Bonnefon }
125bb02e0acSNicolas Bonnefon
126da4beab3SNicolas Bonnefon if ( vm.count( "debug" ) )
127bb02e0acSNicolas Bonnefon logLevel = logINFO;
128da4beab3SNicolas Bonnefon
129da4beab3SNicolas Bonnefon if ( vm.count( "multi" ) )
130da4beab3SNicolas Bonnefon multi_instance = true;
131da4beab3SNicolas Bonnefon
132da4beab3SNicolas Bonnefon if ( vm.count( "new-session" ) )
133da4beab3SNicolas Bonnefon new_session = true;
134bb02e0acSNicolas Bonnefon
1351e522573SNicolas Bonnefon if ( vm.count( "load-session" ) )
1361e522573SNicolas Bonnefon load_session = true;
1371e522573SNicolas Bonnefon
138320f9110SNicolas Bonnefon #ifdef _WIN32
139320f9110SNicolas Bonnefon if ( vm.count( "log" ) )
140320f9110SNicolas Bonnefon log_to_file = true;
141320f9110SNicolas Bonnefon #endif
142320f9110SNicolas Bonnefon
143bb02e0acSNicolas Bonnefon for ( string s = "dd"; s.length() <= 10; s.append("d") )
144bb02e0acSNicolas Bonnefon if ( vm.count( s ) )
145bb02e0acSNicolas Bonnefon logLevel = (TLogLevel) (logWARNING + s.length());
146bb02e0acSNicolas Bonnefon
147661d48b0SNicolas Bonnefon if ( vm.count("input-file") ) {
1481311017aSAnton Filimonov filenames = vm["input-file"].as<vector<string>>();
149bb02e0acSNicolas Bonnefon }
150661d48b0SNicolas Bonnefon }
151bb02e0acSNicolas Bonnefon catch(exception& e) {
152bb02e0acSNicolas Bonnefon cerr << "Option processing error: " << e.what() << endl;
153bb02e0acSNicolas Bonnefon return 1;
154bb02e0acSNicolas Bonnefon }
155bb02e0acSNicolas Bonnefon catch(...) {
156bb02e0acSNicolas Bonnefon cerr << "Exception of unknown type!\n";
157bb02e0acSNicolas Bonnefon }
158bb02e0acSNicolas Bonnefon
159320f9110SNicolas Bonnefon #ifdef _WIN32
160320f9110SNicolas Bonnefon if ( log_to_file )
161320f9110SNicolas Bonnefon {
162320f9110SNicolas Bonnefon char file_name[255];
163320f9110SNicolas Bonnefon snprintf( file_name, sizeof file_name, "glogg_%d.log", getpid() );
164320f9110SNicolas Bonnefon FILE* file = fopen(file_name, "w");
165bb02e0acSNicolas Bonnefon Output2FILE::Stream() = file;
166320f9110SNicolas Bonnefon }
167bb02e0acSNicolas Bonnefon #endif
168bb02e0acSNicolas Bonnefon
169bb02e0acSNicolas Bonnefon FILELog::setReportingLevel( logLevel );
170bb02e0acSNicolas Bonnefon
1711311017aSAnton Filimonov for ( auto& filename: filenames ) {
17265076e27SNicolas Bonnefon if ( ! filename.empty() ) {
17365076e27SNicolas Bonnefon // Convert to absolute path
174661d48b0SNicolas Bonnefon QFileInfo file( QString::fromLocal8Bit( filename.c_str() ) );
17565076e27SNicolas Bonnefon filename = file.absoluteFilePath().toStdString();
176661d48b0SNicolas Bonnefon LOG( logDEBUG ) << "Filename: " << filename;
17765076e27SNicolas Bonnefon }
1781311017aSAnton Filimonov }
17965076e27SNicolas Bonnefon
180e07da50aSNicolas Bonnefon // External communicator
181da4beab3SNicolas Bonnefon shared_ptr<ExternalCommunicator> externalCommunicator = nullptr;
182da4beab3SNicolas Bonnefon shared_ptr<ExternalInstance> externalInstance = nullptr;
183da4beab3SNicolas Bonnefon
184da4beab3SNicolas Bonnefon try {
18515af0893SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_DBUS
186da4beab3SNicolas Bonnefon externalCommunicator = make_shared<DBusExternalCommunicator>();
18724895119SNicolas Bonnefon externalInstance = shared_ptr<ExternalInstance>(
18824895119SNicolas Bonnefon externalCommunicator->otherInstance() );
1892d1bee56SNicolas Bonnefon #elif GLOGG_SUPPORTS_SOCKETIPC
1902d1bee56SNicolas Bonnefon externalCommunicator = make_shared<SocketExternalCommunicator>();
1912d1bee56SNicolas Bonnefon auto ptr = externalCommunicator->otherInstance();
1922d1bee56SNicolas Bonnefon externalInstance = shared_ptr<ExternalInstance>( ptr );
1932d1bee56SNicolas Bonnefon #endif
194da4beab3SNicolas Bonnefon }
195da4beab3SNicolas Bonnefon catch(CantCreateExternalErr& e) {
196da4beab3SNicolas Bonnefon LOG(logWARNING) << "Cannot initialise external communication.";
197da4beab3SNicolas Bonnefon }
198557fb9d8SNicolas Bonnefon
199e07da50aSNicolas Bonnefon LOG(logDEBUG) << "externalInstance = " << externalInstance;
200da4beab3SNicolas Bonnefon if ( ( ! multi_instance ) && externalInstance ) {
201e07da50aSNicolas Bonnefon uint32_t version = externalInstance->getVersion();
202e07da50aSNicolas Bonnefon LOG(logINFO) << "Found another glogg (version = "
203e07da50aSNicolas Bonnefon << std::setbase(16) << version << ")";
204e07da50aSNicolas Bonnefon
2051311017aSAnton Filimonov for ( const auto& filename: filenames ) {
20609aff35dSNicolas Bonnefon externalInstance->loadFile( QString::fromStdString( filename ) );
2071311017aSAnton Filimonov }
20809aff35dSNicolas Bonnefon
209e07da50aSNicolas Bonnefon return 0;
210e07da50aSNicolas Bonnefon }
211e07da50aSNicolas Bonnefon else {
212e07da50aSNicolas Bonnefon // FIXME: there is a race condition here. One glogg could start
213e07da50aSNicolas Bonnefon // between the declaration of externalInstance and here,
214e07da50aSNicolas Bonnefon // is it a problem?
215da4beab3SNicolas Bonnefon if ( externalCommunicator )
216e07da50aSNicolas Bonnefon externalCommunicator->startListening();
217e07da50aSNicolas Bonnefon }
218e07da50aSNicolas Bonnefon
219812146a8SNicolas Bonnefon // Register types for Qt
220812146a8SNicolas Bonnefon qRegisterMetaType<LoadingStatus>("LoadingStatus");
221812146a8SNicolas Bonnefon
222bb02e0acSNicolas Bonnefon // Register the configuration items
223bb02e0acSNicolas Bonnefon GetPersistentInfo().migrateAndInit();
224bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable(
22511582726SNicolas Bonnefon std::make_shared<SessionInfo>(), QString( "session" ) );
226bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable(
22711582726SNicolas Bonnefon std::make_shared<Configuration>(), QString( "settings" ) );
228bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable(
22911582726SNicolas Bonnefon std::make_shared<FilterSet>(), QString( "filterSet" ) );
230bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable(
23111582726SNicolas Bonnefon std::make_shared<SavedSearches>(), QString( "savedSearches" ) );
232bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable(
23311582726SNicolas Bonnefon std::make_shared<RecentFiles>(), QString( "recentFiles" ) );
234a3f81147SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_VERSION_CHECKING
235a3f81147SNicolas Bonnefon GetPersistentInfo().registerPersistable(
236a3f81147SNicolas Bonnefon std::make_shared<VersionCheckerConfig>(), QString( "versionChecker" ) );
237a3f81147SNicolas Bonnefon #endif
238bb02e0acSNicolas Bonnefon
239cf609627SNicolas Bonnefon #ifdef _WIN32
240cf609627SNicolas Bonnefon // Allow the app to raise it's own windows (in case an external
241cf609627SNicolas Bonnefon // glogg send us a file to open)
242cf609627SNicolas Bonnefon AllowSetForegroundWindow(ASFW_ANY);
243cf609627SNicolas Bonnefon #endif
244cf609627SNicolas Bonnefon
2457999f43eSNicolas Bonnefon // We support high-dpi (aka Retina) displays
2467999f43eSNicolas Bonnefon app.setAttribute( Qt::AA_UseHighDpiPixmaps );
247a3dab889SNicolas Bonnefon
248a3dab889SNicolas Bonnefon // No icon in menus
249a3dab889SNicolas Bonnefon app.setAttribute( Qt::AA_DontShowIconsInMenus );
2507999f43eSNicolas Bonnefon
251bb02e0acSNicolas Bonnefon // FIXME: should be replaced by a two staged init of MainWindow
252bb02e0acSNicolas Bonnefon GetPersistentInfo().retrieve( QString( "settings" ) );
253bb02e0acSNicolas Bonnefon
254d96f3f21SNicolas Bonnefon std::unique_ptr<Session> session( new Session() );
25509aff35dSNicolas Bonnefon MainWindow mw( std::move( session ), externalCommunicator );
256bb02e0acSNicolas Bonnefon
257d1edc4fcSNicolas Bonnefon // Geometry
258d1edc4fcSNicolas Bonnefon mw.reloadGeometry();
2593b104697SAnton Filimonov
2601e522573SNicolas Bonnefon // Load the existing session if needed
2613b104697SAnton Filimonov std::shared_ptr<Configuration> config =
2623b104697SAnton Filimonov Persistent<Configuration>( "settings" );
2631311017aSAnton Filimonov if ( load_session || ( filenames.empty() && !new_session && config->loadLastSession() ) )
2640f9fd9edSNicolas Bonnefon mw.reloadSession();
2653b104697SAnton Filimonov
266d1edc4fcSNicolas Bonnefon LOG(logDEBUG) << "MainWindow created.";
267d1edc4fcSNicolas Bonnefon mw.show();
268d1edc4fcSNicolas Bonnefon
2691311017aSAnton Filimonov for ( const auto& filename: filenames ) {
2700f9fd9edSNicolas Bonnefon mw.loadInitialFile( QString::fromStdString( filename ) );
2711311017aSAnton Filimonov }
2721311017aSAnton Filimonov
2738a9275b2SNicolas Bonnefon mw.startBackgroundTasks();
274a9448ba0SNicolas Bonnefon
275bb02e0acSNicolas Bonnefon return app.exec();
276bb02e0acSNicolas Bonnefon }
277bb02e0acSNicolas Bonnefon
print_version()278bb02e0acSNicolas Bonnefon static void print_version()
279bb02e0acSNicolas Bonnefon {
280bb02e0acSNicolas Bonnefon cout << "glogg " GLOGG_VERSION "\n";
281bb02e0acSNicolas Bonnefon #ifdef GLOGG_COMMIT
282bb02e0acSNicolas Bonnefon cout << "Built " GLOGG_DATE " from " GLOGG_COMMIT "\n";
283bb02e0acSNicolas Bonnefon #endif
284d022340fSNicolas Bonnefon cout << "Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicolas Bonnefon and other contributors\n";
285bb02e0acSNicolas Bonnefon cout << "This is free software. You may redistribute copies of it under the terms of\n";
286bb02e0acSNicolas Bonnefon cout << "the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n";
287bb02e0acSNicolas Bonnefon cout << "There is NO WARRANTY, to the extent permitted by law.\n";
288bb02e0acSNicolas Bonnefon }
289