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> 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 35bb02e0acSNicolas Bonnefon #include "persistentinfo.h" 36bb02e0acSNicolas Bonnefon #include "sessioninfo.h" 37bb02e0acSNicolas Bonnefon #include "configuration.h" 38bb02e0acSNicolas Bonnefon #include "filterset.h" 39bb02e0acSNicolas Bonnefon #include "recentfiles.h" 40d96f3f21SNicolas Bonnefon #include "session.h" 41bb02e0acSNicolas Bonnefon #include "mainwindow.h" 42bb02e0acSNicolas Bonnefon #include "savedsearches.h" 43812146a8SNicolas Bonnefon #include "loadingstatus.h" 4415af0893SNicolas Bonnefon 4515af0893SNicolas Bonnefon #include "externalcom.h" 4615af0893SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_DBUS 47557fb9d8SNicolas Bonnefon #include "dbusexternalcom.h" 4824895119SNicolas Bonnefon #elif GLOGG_SUPPORTS_WINIPC 4924895119SNicolas Bonnefon #include "winexternalcom.h" 5015af0893SNicolas Bonnefon #endif 5115af0893SNicolas Bonnefon 5224895119SNicolas Bonnefon 53bb02e0acSNicolas Bonnefon #include "log.h" 54bb02e0acSNicolas Bonnefon 55bb02e0acSNicolas Bonnefon static void print_version(); 56bb02e0acSNicolas Bonnefon 57bb02e0acSNicolas Bonnefon int main(int argc, char *argv[]) 58bb02e0acSNicolas Bonnefon { 59bb02e0acSNicolas Bonnefon QApplication app(argc, argv); 60bb02e0acSNicolas Bonnefon 61bb02e0acSNicolas Bonnefon string filename = ""; 62bb02e0acSNicolas Bonnefon 63da4beab3SNicolas Bonnefon // Configuration 64da4beab3SNicolas Bonnefon bool new_session = false; 65da4beab3SNicolas Bonnefon bool multi_instance = false; 66320f9110SNicolas Bonnefon #ifdef _WIN32 67320f9110SNicolas Bonnefon bool log_to_file = false; 68320f9110SNicolas Bonnefon #endif 69da4beab3SNicolas Bonnefon 70bb02e0acSNicolas Bonnefon TLogLevel logLevel = logWARNING; 71bb02e0acSNicolas Bonnefon 72bb02e0acSNicolas Bonnefon try { 73bb02e0acSNicolas Bonnefon po::options_description desc("Usage: glogg [options] [file]"); 74bb02e0acSNicolas Bonnefon desc.add_options() 75bb02e0acSNicolas Bonnefon ("help,h", "print out program usage (this message)") 76bb02e0acSNicolas Bonnefon ("version,v", "print glogg's version information") 77da4beab3SNicolas Bonnefon ("multi,m", "allow multiple instance of glogg to run simultaneously (use together with -s)") 78da4beab3SNicolas Bonnefon ("new-session,s", "do not load the previous session") 79320f9110SNicolas Bonnefon #ifdef _WIN32 80320f9110SNicolas Bonnefon ("log,l", "save the log to a file (Windows only)") 81320f9110SNicolas Bonnefon #endif 82bb02e0acSNicolas Bonnefon ("debug,d", "output more debug (include multiple times for more verbosity e.g. -dddd") 83bb02e0acSNicolas Bonnefon ; 84bb02e0acSNicolas Bonnefon po::options_description desc_hidden("Hidden options"); 85bb02e0acSNicolas Bonnefon // For -dd, -ddd... 86bb02e0acSNicolas Bonnefon for ( string s = "dd"; s.length() <= 10; s.append("d") ) 87bb02e0acSNicolas Bonnefon desc_hidden.add_options()(s.c_str(), "debug"); 88bb02e0acSNicolas Bonnefon 89bb02e0acSNicolas Bonnefon desc_hidden.add_options() 90bb02e0acSNicolas Bonnefon ("input-file", po::value<string>(), "input file") 91bb02e0acSNicolas Bonnefon ; 92bb02e0acSNicolas Bonnefon 93bb02e0acSNicolas Bonnefon po::options_description all_options("all options"); 94bb02e0acSNicolas Bonnefon all_options.add(desc).add(desc_hidden); 95bb02e0acSNicolas Bonnefon 96bb02e0acSNicolas Bonnefon po::positional_options_description positional; 97bb02e0acSNicolas Bonnefon positional.add("input-file", 1); 98bb02e0acSNicolas Bonnefon 99bb02e0acSNicolas Bonnefon int command_line_style = (((po::command_line_style::unix_style ^ 100bb02e0acSNicolas Bonnefon po::command_line_style::allow_guessing) | 101bb02e0acSNicolas Bonnefon po::command_line_style::allow_long_disguise) ^ 102bb02e0acSNicolas Bonnefon po::command_line_style::allow_sticky); 103bb02e0acSNicolas Bonnefon 104bb02e0acSNicolas Bonnefon po::variables_map vm; 105bb02e0acSNicolas Bonnefon po::store(po::command_line_parser(argc, argv). 106bb02e0acSNicolas Bonnefon options(all_options). 107bb02e0acSNicolas Bonnefon positional(positional). 108bb02e0acSNicolas Bonnefon style(command_line_style).run(), 109bb02e0acSNicolas Bonnefon vm); 110bb02e0acSNicolas Bonnefon po::notify(vm); 111bb02e0acSNicolas Bonnefon 112bb02e0acSNicolas Bonnefon if ( vm.count("help") ) { 113bb02e0acSNicolas Bonnefon desc.print(cout); 114bb02e0acSNicolas Bonnefon return 0; 115bb02e0acSNicolas Bonnefon } 116bb02e0acSNicolas Bonnefon 117bb02e0acSNicolas Bonnefon if ( vm.count("version") ) { 118bb02e0acSNicolas Bonnefon print_version(); 119bb02e0acSNicolas Bonnefon return 0; 120bb02e0acSNicolas Bonnefon } 121bb02e0acSNicolas Bonnefon 122da4beab3SNicolas Bonnefon if ( vm.count( "debug" ) ) 123bb02e0acSNicolas Bonnefon logLevel = logINFO; 124da4beab3SNicolas Bonnefon 125da4beab3SNicolas Bonnefon if ( vm.count( "multi" ) ) 126da4beab3SNicolas Bonnefon multi_instance = true; 127da4beab3SNicolas Bonnefon 128da4beab3SNicolas Bonnefon if ( vm.count( "new-session" ) ) 129da4beab3SNicolas Bonnefon new_session = true; 130bb02e0acSNicolas Bonnefon 131320f9110SNicolas Bonnefon #ifdef _WIN32 132320f9110SNicolas Bonnefon if ( vm.count( "log" ) ) 133320f9110SNicolas Bonnefon log_to_file = true; 134320f9110SNicolas Bonnefon #endif 135320f9110SNicolas Bonnefon 136bb02e0acSNicolas Bonnefon for ( string s = "dd"; s.length() <= 10; s.append("d") ) 137bb02e0acSNicolas Bonnefon if ( vm.count( s ) ) 138bb02e0acSNicolas Bonnefon logLevel = (TLogLevel) (logWARNING + s.length()); 139bb02e0acSNicolas Bonnefon 140bb02e0acSNicolas Bonnefon if ( vm.count("input-file") ) 141bb02e0acSNicolas Bonnefon filename = vm["input-file"].as<string>(); 142bb02e0acSNicolas Bonnefon } 143bb02e0acSNicolas Bonnefon catch(exception& e) { 144bb02e0acSNicolas Bonnefon cerr << "Option processing error: " << e.what() << endl; 145bb02e0acSNicolas Bonnefon return 1; 146bb02e0acSNicolas Bonnefon } 147bb02e0acSNicolas Bonnefon catch(...) { 148bb02e0acSNicolas Bonnefon cerr << "Exception of unknown type!\n"; 149bb02e0acSNicolas Bonnefon } 150bb02e0acSNicolas Bonnefon 151320f9110SNicolas Bonnefon #ifdef _WIN32 152320f9110SNicolas Bonnefon if ( log_to_file ) 153320f9110SNicolas Bonnefon { 154320f9110SNicolas Bonnefon char file_name[255]; 155320f9110SNicolas Bonnefon snprintf( file_name, sizeof file_name, "glogg_%d.log", getpid() ); 156320f9110SNicolas Bonnefon FILE* file = fopen(file_name, "w"); 157bb02e0acSNicolas Bonnefon Output2FILE::Stream() = file; 158320f9110SNicolas Bonnefon } 159bb02e0acSNicolas Bonnefon #endif 160bb02e0acSNicolas Bonnefon 161bb02e0acSNicolas Bonnefon FILELog::setReportingLevel( logLevel ); 162bb02e0acSNicolas Bonnefon 163e07da50aSNicolas Bonnefon // External communicator 164da4beab3SNicolas Bonnefon shared_ptr<ExternalCommunicator> externalCommunicator = nullptr; 165da4beab3SNicolas Bonnefon shared_ptr<ExternalInstance> externalInstance = nullptr; 166da4beab3SNicolas Bonnefon 167da4beab3SNicolas Bonnefon try { 16815af0893SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_DBUS 169da4beab3SNicolas Bonnefon externalCommunicator = make_shared<DBusExternalCommunicator>(); 170da4beab3SNicolas Bonnefon externalInstance = shared_ptr<ExternalInstance>( 171da4beab3SNicolas Bonnefon externalCommunicator->otherInstance() ); 17224895119SNicolas Bonnefon #elif GLOGG_SUPPORTS_WINIPC 17324895119SNicolas Bonnefon externalCommunicator = make_shared<WinExternalCommunicator>(); 17424895119SNicolas Bonnefon externalInstance = shared_ptr<ExternalInstance>( 17524895119SNicolas Bonnefon externalCommunicator->otherInstance() ); 17615af0893SNicolas Bonnefon #endif 177da4beab3SNicolas Bonnefon } 178da4beab3SNicolas Bonnefon catch(CantCreateExternalErr& e) { 179da4beab3SNicolas Bonnefon LOG(logWARNING) << "Cannot initialise external communication."; 180da4beab3SNicolas Bonnefon } 181557fb9d8SNicolas Bonnefon 182e07da50aSNicolas Bonnefon LOG(logDEBUG) << "externalInstance = " << externalInstance; 183da4beab3SNicolas Bonnefon if ( ( ! multi_instance ) && externalInstance ) { 184e07da50aSNicolas Bonnefon uint32_t version = externalInstance->getVersion(); 185e07da50aSNicolas Bonnefon LOG(logINFO) << "Found another glogg (version = " 186e07da50aSNicolas Bonnefon << std::setbase(16) << version << ")"; 187e07da50aSNicolas Bonnefon 18809aff35dSNicolas Bonnefon externalInstance->loadFile( QString::fromStdString( filename ) ); 18909aff35dSNicolas Bonnefon 190e07da50aSNicolas Bonnefon return 0; 191e07da50aSNicolas Bonnefon } 192e07da50aSNicolas Bonnefon else { 193e07da50aSNicolas Bonnefon // FIXME: there is a race condition here. One glogg could start 194e07da50aSNicolas Bonnefon // between the declaration of externalInstance and here, 195e07da50aSNicolas Bonnefon // is it a problem? 196da4beab3SNicolas Bonnefon if ( externalCommunicator ) 197e07da50aSNicolas Bonnefon externalCommunicator->startListening(); 198e07da50aSNicolas Bonnefon } 199e07da50aSNicolas Bonnefon 200812146a8SNicolas Bonnefon // Register types for Qt 201812146a8SNicolas Bonnefon qRegisterMetaType<LoadingStatus>("LoadingStatus"); 202812146a8SNicolas Bonnefon 203bb02e0acSNicolas Bonnefon // Register the configuration items 204bb02e0acSNicolas Bonnefon GetPersistentInfo().migrateAndInit(); 205bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable( 20611582726SNicolas Bonnefon std::make_shared<SessionInfo>(), QString( "session" ) ); 207bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable( 20811582726SNicolas Bonnefon std::make_shared<Configuration>(), QString( "settings" ) ); 209bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable( 21011582726SNicolas Bonnefon std::make_shared<FilterSet>(), QString( "filterSet" ) ); 211bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable( 21211582726SNicolas Bonnefon std::make_shared<SavedSearches>(), QString( "savedSearches" ) ); 213bb02e0acSNicolas Bonnefon GetPersistentInfo().registerPersistable( 21411582726SNicolas Bonnefon std::make_shared<RecentFiles>(), QString( "recentFiles" ) ); 215*a3f81147SNicolas Bonnefon #ifdef GLOGG_SUPPORTS_VERSION_CHECKING 216*a3f81147SNicolas Bonnefon GetPersistentInfo().registerPersistable( 217*a3f81147SNicolas Bonnefon std::make_shared<VersionCheckerConfig>(), QString( "versionChecker" ) ); 218*a3f81147SNicolas Bonnefon #endif 219bb02e0acSNicolas Bonnefon 220bb02e0acSNicolas Bonnefon // FIXME: should be replaced by a two staged init of MainWindow 221bb02e0acSNicolas Bonnefon GetPersistentInfo().retrieve( QString( "settings" ) ); 222bb02e0acSNicolas Bonnefon 223d96f3f21SNicolas Bonnefon std::unique_ptr<Session> session( new Session() ); 22409aff35dSNicolas Bonnefon MainWindow mw( std::move( session ), externalCommunicator ); 225bb02e0acSNicolas Bonnefon 226bb02e0acSNicolas Bonnefon LOG(logDEBUG) << "MainWindow created."; 2270f9fd9edSNicolas Bonnefon mw.show(); 228da4beab3SNicolas Bonnefon if ( ! new_session ) 2290f9fd9edSNicolas Bonnefon mw.reloadSession(); 2300f9fd9edSNicolas Bonnefon mw.loadInitialFile( QString::fromStdString( filename ) ); 2318a9275b2SNicolas Bonnefon mw.startBackgroundTasks(); 232bb02e0acSNicolas Bonnefon return app.exec(); 233bb02e0acSNicolas Bonnefon } 234bb02e0acSNicolas Bonnefon 235bb02e0acSNicolas Bonnefon static void print_version() 236bb02e0acSNicolas Bonnefon { 237bb02e0acSNicolas Bonnefon cout << "glogg " GLOGG_VERSION "\n"; 238bb02e0acSNicolas Bonnefon #ifdef GLOGG_COMMIT 239bb02e0acSNicolas Bonnefon cout << "Built " GLOGG_DATE " from " GLOGG_COMMIT "\n"; 240bb02e0acSNicolas Bonnefon #endif 2418a9275b2SNicolas Bonnefon cout << "Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Nicolas Bonnefon and other contributors\n"; 242bb02e0acSNicolas Bonnefon cout << "This is free software. You may redistribute copies of it under the terms of\n"; 243bb02e0acSNicolas Bonnefon cout << "the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"; 244bb02e0acSNicolas Bonnefon cout << "There is NO WARRANTY, to the extent permitted by law.\n"; 245bb02e0acSNicolas Bonnefon } 246