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