UniversalIndentGUI 1.2.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2006-2012 by Thomas Schweitzer * 00003 * thomas-schweitzer(at)arcor.de * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License version 2.0 as * 00007 * published by the Free Software Foundation. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License * 00015 * along with this program in the file LICENSE.GPL; if not, write to the * 00016 * Free Software Foundation, Inc., * 00017 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00018 ***************************************************************************/ 00019 00020 #include "MainWindow.h" 00021 00022 #include "UiGuiIndentServer.h" 00023 #include "debugging/TSLogger.h" 00024 #include "UiGuiIniFileParser.h" 00025 #include "UiGuiSettings.h" 00026 #include "UiGuiVersion.h" 00027 #include "UiGuiSystemInfo.h" 00028 #include "IndentHandler.h" 00029 #include "SettingsPaths.h" 00030 00031 #include <QApplication> 00032 #include <QTextCodec> 00033 #include <QDebug> 00034 00035 #include <string> 00036 #include <iostream> 00037 #include <algorithm> 00038 #include <tclap/CmdLine.h> 00039 00040 #ifdef _MSC_VER 00041 00042 #include <windows.h> 00043 #include <direct.h> 00044 #include <stdlib.h> 00045 #include <stdio.h> 00046 #include <fcntl.h> 00047 #include <io.h> 00048 #include <iostream> 00049 #include <fstream> 00050 00059 bool attachToConsole(/*enum ATTACH_ONLY|TRY_ATTACH_ELSE_CREATE|CREATE_NEW*/) 00060 { 00061 int hConHandle; 00062 long lStdHandle; 00063 CONSOLE_SCREEN_BUFFER_INFO coninfo; 00064 FILE *fp; 00065 00066 // Trying to attach to the console of the parent process. 00067 BOOL successful = AttachConsole(ATTACH_PARENT_PROCESS); 00068 // In case that the parent process has no console return false and do no input/output redirection. 00069 if ( !successful ) 00070 return false; 00071 00072 // Set the screen buffer to be big enough to let us scroll text 00073 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); 00074 // Set maximum console lines. 00075 coninfo.dwSize.Y = 500; 00076 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); 00077 00078 // Redirect unbuffered STDOUT to the console. 00079 lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); 00080 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 00081 if ( hConHandle != -1 ) { 00082 fp = _fdopen( hConHandle, "w" ); 00083 *stdout = *fp; 00084 setvbuf( stdout, NULL, _IONBF, 0 ); 00085 } 00086 00087 // Redirect unbuffered STDIN to the console. 00088 lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); 00089 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 00090 if ( hConHandle != -1 ) { 00091 fp = _fdopen( hConHandle, "r" ); 00092 *stdin = *fp; 00093 setvbuf( stdin, NULL, _IONBF, 0 ); 00094 } 00095 00096 // Redirect unbuffered STDERR to the console. 00097 lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); 00098 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 00099 if ( hConHandle != -1 ) { 00100 fp = _fdopen( hConHandle, "w" ); 00101 *stderr = *fp; 00102 setvbuf( stderr, NULL, _IONBF, 0 ); 00103 } 00104 00105 // Make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well. 00106 std::ios::sync_with_stdio(); 00107 00108 return true; 00109 } 00110 #else 00111 bool attachToConsole() 00112 { 00113 return false; 00114 } 00115 00116 #endif 00117 00118 using namespace tschweitzer::debugging; 00119 00131 int main(int argc, char *argv[]) { 00132 QString file2OpenOnStart = ""; 00133 int verboseLevel = 1; 00134 bool startAsPlugin = false; 00135 bool startAsServer = false; 00136 bool tclapExitExceptionThrown = false; 00137 int returnValue = 0; 00138 00139 bool attachedToConsole = false; 00140 attachedToConsole = attachToConsole(); 00141 00142 #ifdef __APPLE__ 00143 // Filter out -psn_0_118813 and similar parameters. 00144 std::vector<char*> argList; 00145 for ( int i = 0; i < argc; i++ ) { 00146 QString argString(argv[i]); 00147 00148 if ( argString.startsWith("-psn_") == false ) { 00149 argList.push_back(argv[i]); 00150 } 00151 else { 00152 // std::cerr << std::endl << "The parameter "<< i << " is an invalid finder parameter. Parameter was " << argv[i] << std::endl; 00153 } 00154 } 00155 for ( size_t i = 0; i < argList.size(); i++ ) { 00156 argv[i] = argList.at(i); 00157 } 00158 argc = argList.size(); 00159 #endif 00160 00161 // Wrap everything in a try block. Do this every time, 00162 // because exceptions will be thrown for problems. 00163 try { 00164 // Define the command line object. 00165 TCLAP::CmdLine cmd("If -p and -s are set, -p will be used.\nGiving no parameters starts full gui without server.", ' ', "UiGUI version " PROGRAM_VERSION_STRING " " PROGRAM_REVISION); 00166 cmd.setExceptionHandling(false); 00167 00168 // Define a value argument and add it to the command line. 00169 TCLAP::UnlabeledValueArg<std::string> filenameArg("file", "Opens the by filename defined file on start" , false, "", "filename"); 00170 cmd.add( filenameArg ); 00171 00172 // Define a switch and add it to the command line. 00173 TCLAP::SwitchArg pluginSwitch("p", "plugin", "Run as plugin. Server will be started with a simplified gui", false); 00174 cmd.add( pluginSwitch ); 00175 00176 // Define a switch and add it to the command line. 00177 TCLAP::SwitchArg serverSwitch("s", "server", "Run as server only without gui", false); 00178 cmd.add( serverSwitch ); 00179 00180 // Define a value argument and add it to the command line. 00181 TCLAP::ValueArg<int> verboselevelArg("v", "verbose", "Sets how many info is written to the log. 0 means with debug info, 3 means critical messages only" , false, 1, "int"); 00182 cmd.add( verboselevelArg ); 00183 00184 // Parse the args. 00185 cmd.parse( argc, argv ); 00186 00187 // Get the value parsed by each arg. 00188 file2OpenOnStart = filenameArg.getValue().c_str(); 00189 startAsPlugin = pluginSwitch.getValue(); 00190 startAsServer = serverSwitch.getValue(); 00191 verboseLevel = verboselevelArg.getValue(); 00192 } 00193 catch (TCLAP::ArgException &e) { // catch arg exceptions 00194 std::cerr << std::endl << "error: " << e.error() << ". " << e.argId() << std::endl; 00195 returnValue = 1; 00196 } 00197 catch (TCLAP::ExitException &e) { // catch exit exceptions 00198 tclapExitExceptionThrown = true; 00199 returnValue = e.getExitStatus(); 00200 } 00201 catch (...) { // catch any exceptions 00202 std::cerr << std::endl << "There was an error! Maybe faulty command line arguments set. See --help." << std::endl; 00203 returnValue = 1; 00204 } 00205 00206 if ( returnValue != 0 || tclapExitExceptionThrown ) { 00207 #ifdef _MSC_VER 00208 if ( attachedToConsole ) { 00209 // Workaround for skipped command line prompt: Get the current working directory and print it to console. 00210 char* buffer; 00211 if( (buffer = _getcwd( NULL, 0 )) != NULL ) { 00212 std::cerr << std::endl << buffer << ">"; 00213 free(buffer); 00214 } 00215 // Release the connection to the parents console. 00216 FreeConsole(); 00217 } 00218 #endif 00219 return returnValue; 00220 } 00221 00222 QApplication app(argc, argv); 00223 UiGuiIndentServer server; 00224 MainWindow *mainWindow = NULL; 00225 IndentHandler *indentHandler = NULL; 00226 00227 // Init and install the logger function. 00228 // Setting UTF-8 as default 8-Bit encoding to ensure that qDebug does no false string conversion. 00229 QTextCodec::setCodecForCStrings( QTextCodec::codecForName("UTF-8") ); 00230 QTextCodec::setCodecForLocale( QTextCodec::codecForName("UTF-8") ); 00231 // Force creation of an TSLogger instance here, to avoid recursion with SettingsPaths init function. 00232 #ifdef _DEBUG 00233 TSLogger::getInstance(0); 00234 #else 00235 TSLogger::getInstance(verboseLevel); 00236 #endif 00237 qInstallMsgHandler( TSLogger::messageHandler ); 00238 TSLogger::messageHandler( TSLoggerInfoMsg, QString("Starting UiGUI Version %1 %2").arg(PROGRAM_VERSION_STRING).arg(PROGRAM_REVISION).toAscii() ); 00239 TSLogger::messageHandler( TSLoggerInfoMsg, QString("Running on %1").arg(UiGuiSystemInfo::getOperatingSystem()).toAscii() ); 00240 00241 // Set default values for all by UniversalIndentGUI used settings objects. 00242 QCoreApplication::setOrganizationName("UniversalIndentGUI"); 00243 QCoreApplication::setOrganizationDomain("universalindent.sf.net"); 00244 QCoreApplication::setApplicationName("UniversalIndentGUI"); 00245 00246 // Start normal with full gui and without server. 00247 if ( !startAsPlugin && !startAsServer ) { 00248 mainWindow = new MainWindow(file2OpenOnStart); 00249 mainWindow->show(); 00250 } 00251 // Start as plugin with server. 00252 else if ( startAsPlugin ) { 00253 server.startServer(); 00254 indentHandler = new IndentHandler(0); 00255 indentHandler->show(); 00256 } 00257 // Start as server only without any gui. 00258 else if ( startAsServer ) { 00259 server.startServer(); 00260 } 00261 00262 try { 00263 returnValue = app.exec(); 00264 } 00265 catch (std::exception &ex) { 00266 qCritical() << __LINE__ << " " << __FUNCTION__ << ": Something went terribly wrong:" << ex.what(); 00267 } 00268 00269 if ( startAsPlugin || startAsServer ) 00270 server.stopServer(); 00271 00272 delete indentHandler; 00273 delete mainWindow; 00274 00275 SettingsPaths::cleanAndRemoveTempDir(); 00276 TSLogger::deleteInstance(); 00277 00278 return returnValue; 00279 }