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 #include <QFileInfo> 22 23 #include <memory> 24 25 #include <boost/program_options.hpp> 26 namespace po = boost::program_options; 27 28 #include <iostream> 29 #include <iomanip> 30 using namespace std; 31 32 #ifdef _WIN32 33 #include "unistd.h" 34 #endif 35 36 #include "persistentinfo.h" 37 #include "sessioninfo.h" 38 #include "configuration.h" 39 #include "filterset.h" 40 #include "recentfiles.h" 41 #include "session.h" 42 #include "mainwindow.h" 43 #include "savedsearches.h" 44 #include "loadingstatus.h" 45 46 #include "externalcom.h" 47 #ifdef GLOGG_SUPPORTS_DBUS 48 #include "dbusexternalcom.h" 49 #elif GLOGG_SUPPORTS_WINIPC 50 #include "winexternalcom.h" 51 #endif 52 53 54 #include "log.h" 55 56 static void print_version(); 57 58 int main(int argc, char *argv[]) 59 { 60 QApplication app(argc, argv); 61 62 string filename = ""; 63 64 // Configuration 65 bool new_session = false; 66 bool load_session = false; 67 bool multi_instance = false; 68 #ifdef _WIN32 69 bool log_to_file = false; 70 #endif 71 72 TLogLevel logLevel = logWARNING; 73 74 try { 75 po::options_description desc("Usage: glogg [options] [file]"); 76 desc.add_options() 77 ("help,h", "print out program usage (this message)") 78 ("version,v", "print glogg's version information") 79 ("multi,m", "allow multiple instance of glogg to run simultaneously (use together with -s)") 80 ("load-session,s", "load the previous session (default when no file is passed)") 81 ("new-session,n", "do not load the previous session (default when a file is passed)") 82 #ifdef _WIN32 83 ("log,l", "save the log to a file (Windows only)") 84 #endif 85 ("debug,d", "output more debug (include multiple times for more verbosity e.g. -dddd)") 86 ; 87 po::options_description desc_hidden("Hidden options"); 88 // For -dd, -ddd... 89 for ( string s = "dd"; s.length() <= 10; s.append("d") ) 90 desc_hidden.add_options()(s.c_str(), "debug"); 91 92 desc_hidden.add_options() 93 ("input-file", po::value<string>(), "input file") 94 ; 95 96 po::options_description all_options("all options"); 97 all_options.add(desc).add(desc_hidden); 98 99 po::positional_options_description positional; 100 positional.add("input-file", 1); 101 102 int command_line_style = (((po::command_line_style::unix_style ^ 103 po::command_line_style::allow_guessing) | 104 po::command_line_style::allow_long_disguise) ^ 105 po::command_line_style::allow_sticky); 106 107 po::variables_map vm; 108 po::store(po::command_line_parser(argc, argv). 109 options(all_options). 110 positional(positional). 111 style(command_line_style).run(), 112 vm); 113 po::notify(vm); 114 115 if ( vm.count("help") ) { 116 desc.print(cout); 117 return 0; 118 } 119 120 if ( vm.count("version") ) { 121 print_version(); 122 return 0; 123 } 124 125 if ( vm.count( "debug" ) ) 126 logLevel = logINFO; 127 128 if ( vm.count( "multi" ) ) 129 multi_instance = true; 130 131 if ( vm.count( "new-session" ) ) 132 new_session = true; 133 134 if ( vm.count( "load-session" ) ) 135 load_session = true; 136 137 #ifdef _WIN32 138 if ( vm.count( "log" ) ) 139 log_to_file = true; 140 #endif 141 142 for ( string s = "dd"; s.length() <= 10; s.append("d") ) 143 if ( vm.count( s ) ) 144 logLevel = (TLogLevel) (logWARNING + s.length()); 145 146 if ( vm.count("input-file") ) 147 filename = vm["input-file"].as<string>(); 148 } 149 catch(exception& e) { 150 cerr << "Option processing error: " << e.what() << endl; 151 return 1; 152 } 153 catch(...) { 154 cerr << "Exception of unknown type!\n"; 155 } 156 157 #ifdef _WIN32 158 if ( log_to_file ) 159 { 160 char file_name[255]; 161 snprintf( file_name, sizeof file_name, "glogg_%d.log", getpid() ); 162 FILE* file = fopen(file_name, "w"); 163 Output2FILE::Stream() = file; 164 } 165 #endif 166 167 FILELog::setReportingLevel( logLevel ); 168 169 if ( ! filename.empty() ) { 170 // Convert to absolute path 171 QFileInfo file( QString::fromStdString( filename ) ); 172 filename = file.absoluteFilePath().toStdString(); 173 } 174 175 // External communicator 176 shared_ptr<ExternalCommunicator> externalCommunicator = nullptr; 177 shared_ptr<ExternalInstance> externalInstance = nullptr; 178 179 try { 180 #ifdef GLOGG_SUPPORTS_DBUS 181 externalCommunicator = make_shared<DBusExternalCommunicator>(); 182 externalInstance = shared_ptr<ExternalInstance>( 183 externalCommunicator->otherInstance() ); 184 #elif GLOGG_SUPPORTS_WINIPC 185 externalCommunicator = make_shared<WinExternalCommunicator>(); 186 externalInstance = shared_ptr<ExternalInstance>( 187 externalCommunicator->otherInstance() ); 188 #endif 189 } 190 catch(CantCreateExternalErr& e) { 191 LOG(logWARNING) << "Cannot initialise external communication."; 192 } 193 194 LOG(logDEBUG) << "externalInstance = " << externalInstance; 195 if ( ( ! multi_instance ) && externalInstance ) { 196 uint32_t version = externalInstance->getVersion(); 197 LOG(logINFO) << "Found another glogg (version = " 198 << std::setbase(16) << version << ")"; 199 200 externalInstance->loadFile( QString::fromStdString( filename ) ); 201 202 return 0; 203 } 204 else { 205 // FIXME: there is a race condition here. One glogg could start 206 // between the declaration of externalInstance and here, 207 // is it a problem? 208 if ( externalCommunicator ) 209 externalCommunicator->startListening(); 210 } 211 212 // Register types for Qt 213 qRegisterMetaType<LoadingStatus>("LoadingStatus"); 214 215 // Register the configuration items 216 GetPersistentInfo().migrateAndInit(); 217 GetPersistentInfo().registerPersistable( 218 std::make_shared<SessionInfo>(), QString( "session" ) ); 219 GetPersistentInfo().registerPersistable( 220 std::make_shared<Configuration>(), QString( "settings" ) ); 221 GetPersistentInfo().registerPersistable( 222 std::make_shared<FilterSet>(), QString( "filterSet" ) ); 223 GetPersistentInfo().registerPersistable( 224 std::make_shared<SavedSearches>(), QString( "savedSearches" ) ); 225 GetPersistentInfo().registerPersistable( 226 std::make_shared<RecentFiles>(), QString( "recentFiles" ) ); 227 #ifdef GLOGG_SUPPORTS_VERSION_CHECKING 228 GetPersistentInfo().registerPersistable( 229 std::make_shared<VersionCheckerConfig>(), QString( "versionChecker" ) ); 230 #endif 231 232 #ifdef _WIN32 233 // Allow the app to raise it's own windows (in case an external 234 // glogg send us a file to open) 235 AllowSetForegroundWindow(ASFW_ANY); 236 #endif 237 238 // FIXME: should be replaced by a two staged init of MainWindow 239 GetPersistentInfo().retrieve( QString( "settings" ) ); 240 241 std::unique_ptr<Session> session( new Session() ); 242 MainWindow mw( std::move( session ), externalCommunicator ); 243 244 LOG(logDEBUG) << "MainWindow created."; 245 mw.show(); 246 // Load the existing session if needed 247 if ( load_session || ( filename.empty() && !new_session ) ) 248 mw.reloadSession(); 249 mw.loadInitialFile( QString::fromStdString( filename ) ); 250 mw.startBackgroundTasks(); 251 252 // We support hi-dpi (aka Retina) 253 app.setAttribute(Qt::AA_UseHighDpiPixmaps); 254 255 return app.exec(); 256 } 257 258 static void print_version() 259 { 260 cout << "glogg " GLOGG_VERSION "\n"; 261 #ifdef GLOGG_COMMIT 262 cout << "Built " GLOGG_DATE " from " GLOGG_COMMIT "\n"; 263 #endif 264 cout << "Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicolas Bonnefon and other contributors\n"; 265 cout << "This is free software. You may redistribute copies of it under the terms of\n"; 266 cout << "the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"; 267 cout << "There is NO WARRANTY, to the extent permitted by law.\n"; 268 } 269