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> 214752846bSNicolas 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" 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 59bb02e0acSNicolas Bonnefon int main(int argc, char *argv[]) 60bb02e0acSNicolas Bonnefon { 61bb02e0acSNicolas Bonnefon QApplication 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 { 76*90d2843cSNicolas 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 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