2009-02-25 09:15:00 +01:00
/**************************************************************************
2008-12-02 12:01:29 +01:00
* *
* * This file is part of Qt Creator
* *
2011-01-11 16:28:15 +01:00
* * Copyright ( c ) 2011 Nokia Corporation and / or its subsidiary ( - ies ) .
2008-12-02 12:01:29 +01:00
* *
2009-06-17 00:01:27 +10:00
* * Contact : Nokia Corporation ( qt - info @ nokia . com )
2008-12-02 12:01:29 +01:00
* *
2010-12-17 16:01:08 +01:00
* * No Commercial Usage
2008-12-02 14:17:16 +01:00
* *
2010-12-17 16:01:08 +01:00
* * This file contains pre - release code and may not be distributed .
* * You may use this file in accordance with the terms and conditions
* * contained in the Technology Preview License Agreement accompanying
* * this package .
2008-12-02 14:17:16 +01:00
* *
2009-02-25 09:15:00 +01:00
* * GNU Lesser General Public License Usage
2008-12-02 14:17:16 +01:00
* *
2009-02-25 09:15:00 +01:00
* * Alternatively , this file may be used under the terms of the GNU Lesser
* * General Public License version 2.1 as published by the Free Software
* * Foundation and appearing in the file LICENSE . LGPL included in the
* * packaging of this file . Please review the following information to
* * ensure the GNU Lesser General Public License version 2.1 requirements
* * will be met : http : //www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2008-12-02 14:17:16 +01:00
* *
2010-12-17 16:01:08 +01:00
* * In addition , as a special exception , Nokia gives you certain additional
* * rights . These rights are described in the Nokia Qt LGPL Exception
* * version 1.1 , included in the file LGPL_EXCEPTION . txt in this package .
* *
* * If you have questions regarding the use of this file , please contact
* * Nokia at qt - info @ nokia . com .
2008-12-02 12:01:29 +01:00
* *
2009-02-25 09:15:00 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-12-02 12:01:29 +01:00
# include "qtsingleapplication.h"
# include <extensionsystem/pluginmanager.h>
# include <extensionsystem/pluginspec.h>
# include <extensionsystem/iplugin.h>
# include <QtCore/QDir>
2010-10-21 18:05:15 +02:00
# include <QtCore/QUrl>
2008-12-02 12:01:29 +01:00
# include <QtCore/QTextStream>
# include <QtCore/QFileInfo>
# include <QtCore/QDebug>
# include <QtCore/QTimer>
2009-04-20 16:41:06 +02:00
# include <QtCore/QLibraryInfo>
# include <QtCore/QTranslator>
2010-01-05 16:33:30 +01:00
# include <QtCore/QSettings>
2009-04-20 16:41:06 +02:00
# include <QtCore/QVariant>
2010-09-13 11:54:55 +02:00
# include <QtCore/QThreadPool>
2008-12-02 12:01:29 +01:00
2010-02-18 17:36:17 +01:00
# include <QtNetwork/QNetworkProxyFactory>
2008-12-02 12:01:29 +01:00
# include <QtGui/QMessageBox>
# include <QtGui/QApplication>
# include <QtGui/QMainWindow>
2010-09-09 19:37:01 +02:00
# ifdef ENABLE_QT_BREAKPAD
# include <qtsystemexceptionhandler.h>
# endif
2010-10-25 18:02:27 +02:00
enum { OptionIndent = 4 , DescriptionIndent = 34 } ;
2008-12-02 12:01:29 +01:00
static const char * appNameC = " Qt Creator " ;
static const char * corePluginNameC = " Core " ;
static const char * fixedOptionsC =
" [OPTION]... [FILE]... \n "
" Options: \n "
2010-10-25 18:02:27 +02:00
" -help Display this help \n "
" -version Display program version \n "
" -client Attempt to connect to already running instance \n "
" -settingspath <path> Override the default path where user settings are stored. \n " ;
2008-12-02 12:01:29 +01:00
static const char * HELP_OPTION1 = " -h " ;
static const char * HELP_OPTION2 = " -help " ;
static const char * HELP_OPTION3 = " /h " ;
static const char * HELP_OPTION4 = " --help " ;
static const char * VERSION_OPTION = " -version " ;
static const char * CLIENT_OPTION = " -client " ;
2010-10-25 18:02:27 +02:00
static const char * SETTINGS_OPTION = " -settingspath " ;
2008-12-02 12:01:29 +01:00
2008-12-11 11:26:42 +01:00
typedef QList < ExtensionSystem : : PluginSpec * > PluginSpecSet ;
2008-12-02 12:01:29 +01:00
// Helpers for displaying messages. Note that there is no console on Windows.
2009-06-03 20:45:49 +02:00
# ifdef Q_OS_WIN
2008-12-02 12:01:29 +01:00
// Format as <pre> HTML
static inline void toHtml ( QString & t )
{
t . replace ( QLatin1Char ( ' & ' ) , QLatin1String ( " & " ) ) ;
t . replace ( QLatin1Char ( ' < ' ) , QLatin1String ( " < " ) ) ;
t . replace ( QLatin1Char ( ' > ' ) , QLatin1String ( " > " ) ) ;
t . insert ( 0 , QLatin1String ( " <html><pre> " ) ) ;
t . append ( QLatin1String ( " </pre></html> " ) ) ;
}
static void displayHelpText ( QString t ) // No console on Windows.
{
toHtml ( t ) ;
QMessageBox : : information ( 0 , QLatin1String ( appNameC ) , t ) ;
}
static void displayError ( const QString & t ) // No console on Windows.
{
QMessageBox : : critical ( 0 , QLatin1String ( appNameC ) , t ) ;
}
# else
static void displayHelpText ( const QString & t )
{
2008-12-19 10:49:29 +01:00
qWarning ( " %s " , qPrintable ( t ) ) ;
2008-12-02 12:01:29 +01:00
}
static void displayError ( const QString & t )
{
2008-12-19 10:49:29 +01:00
qCritical ( " %s " , qPrintable ( t ) ) ;
2008-12-02 12:01:29 +01:00
}
# endif
static void printVersion ( const ExtensionSystem : : PluginSpec * coreplugin ,
const ExtensionSystem : : PluginManager & pm )
{
QString version ;
QTextStream str ( & version ) ;
str < < ' \n ' < < appNameC < < ' ' < < coreplugin - > version ( ) < < " based on Qt " < < qVersion ( ) < < " \n \n " ;
pm . formatPluginVersions ( str ) ;
str < < ' \n ' < < coreplugin - > copyright ( ) < < ' \n ' ;
displayHelpText ( version ) ;
}
static void printHelp ( const QString & a0 , const ExtensionSystem : : PluginManager & pm )
{
QString help ;
QTextStream str ( & help ) ;
str < < " Usage: " < < a0 < < fixedOptionsC ;
ExtensionSystem : : PluginManager : : formatOptions ( str , OptionIndent , DescriptionIndent ) ;
pm . formatPluginOptions ( str , OptionIndent , DescriptionIndent ) ;
displayHelpText ( help ) ;
}
static inline QString msgCoreLoadFailure ( const QString & why )
{
return QCoreApplication : : translate ( " Application " , " Failed to load core: %1 " ) . arg ( why ) ;
}
static inline QString msgSendArgumentFailed ( )
{
return QCoreApplication : : translate ( " Application " , " Unable to send command line arguments to the already running instance. It appears to be not responding. " ) ;
}
static inline QStringList getPluginPaths ( )
{
QStringList rc ;
// Figure out root: Up one from 'bin'
QDir rootDir = QApplication : : applicationDirPath ( ) ;
rootDir . cdUp ( ) ;
2009-07-23 17:04:22 +02:00
const QString rootDirPath = rootDir . canonicalPath ( ) ;
2009-01-21 08:50:53 +01:00
// 1) "plugins" (Win/Linux)
2008-12-02 12:01:29 +01:00
QString pluginPath = rootDirPath ;
2009-07-24 12:11:12 +02:00
pluginPath + = QLatin1Char ( ' / ' ) ;
2009-05-12 16:18:38 +02:00
pluginPath + = QLatin1String ( IDE_LIBRARY_BASENAME ) ;
2009-07-24 12:11:12 +02:00
pluginPath + = QLatin1Char ( ' / ' ) ;
2009-01-21 08:50:53 +01:00
pluginPath + = QLatin1String ( " qtcreator " ) ;
2009-07-24 12:11:12 +02:00
pluginPath + = QLatin1Char ( ' / ' ) ;
2009-01-21 08:50:53 +01:00
pluginPath + = QLatin1String ( " plugins " ) ;
2008-12-02 12:01:29 +01:00
rc . push_back ( pluginPath ) ;
2009-01-21 08:50:53 +01:00
// 2) "PlugIns" (OS X)
2008-12-02 12:01:29 +01:00
pluginPath = rootDirPath ;
2009-07-24 12:11:12 +02:00
pluginPath + = QLatin1Char ( ' / ' ) ;
2008-12-02 12:01:29 +01:00
pluginPath + = QLatin1String ( " PlugIns " ) ;
rc . push_back ( pluginPath ) ;
return rc ;
}
2009-04-20 16:41:06 +02:00
# ifdef Q_OS_MAC
# define SHARE_PATH " / .. / Resources"
# else
# define SHARE_PATH " / .. / share / qtcreator"
# endif
2008-12-02 12:01:29 +01:00
int main ( int argc , char * * argv )
{
2009-06-03 20:45:49 +02:00
# ifdef Q_OS_MAC
2008-12-02 12:01:29 +01:00
// increase the number of file that can be opened in Qt Creator.
struct rlimit rl ;
getrlimit ( RLIMIT_NOFILE , & rl ) ;
2010-05-28 13:45:53 +02:00
rl . rlim_cur = qMin ( ( rlim_t ) OPEN_MAX , rl . rlim_max ) ;
2008-12-02 12:01:29 +01:00
setrlimit ( RLIMIT_NOFILE , & rl ) ;
# endif
SharedTools : : QtSingleApplication app ( ( QLatin1String ( appNameC ) ) , argc , argv ) ;
2009-04-20 16:41:06 +02:00
2010-09-13 11:54:55 +02:00
const int threadCount = QThreadPool : : globalInstance ( ) - > maxThreadCount ( ) ;
QThreadPool : : globalInstance ( ) - > setMaxThreadCount ( qMax ( 4 , 2 * threadCount ) ) ;
2010-09-09 19:37:01 +02:00
# ifdef ENABLE_QT_BREAKPAD
QtSystemExceptionHandler systemExceptionHandler ;
# endif
2009-04-20 16:41:06 +02:00
QTranslator translator ;
QTranslator qtTranslator ;
2009-09-11 14:37:17 +02:00
QString locale = QLocale : : system ( ) . name ( ) ;
2010-01-13 17:04:46 +01:00
2010-10-25 18:02:27 +02:00
// Manually determine -settingspath command line option
// We can't use the regular way of the plugin manager, because that needs to parse pluginspecs
// but the settings path can influence which plugins are enabled
QString settingsPath ;
QStringList arguments = app . arguments ( ) ; /* adapted arguments list is passed to plugin manager later */
QMutableStringListIterator it ( arguments ) ;
while ( it . hasNext ( ) ) {
const QString & arg = it . next ( ) ;
if ( arg = = QLatin1String ( SETTINGS_OPTION ) ) {
it . remove ( ) ;
if ( it . hasNext ( ) ) {
settingsPath = QDir : : fromNativeSeparators ( it . next ( ) ) ;
it . remove ( ) ;
}
}
}
if ( ! settingsPath . isEmpty ( ) )
QSettings : : setPath ( QSettings : : IniFormat , QSettings : : UserScope , settingsPath ) ;
2010-01-13 17:04:46 +01:00
// Must be done before any QSettings class is created
2010-01-14 16:35:44 +01:00
QSettings : : setPath ( QSettings : : IniFormat , QSettings : : SystemScope ,
QCoreApplication : : applicationDirPath ( ) + QLatin1String ( SHARE_PATH ) ) ;
2010-10-25 16:57:58 +02:00
// plugin manager takes control of this settings object
QSettings * settings = new QSettings ( QSettings : : IniFormat , QSettings : : UserScope ,
2010-01-05 16:33:30 +01:00
QLatin1String ( " Nokia " ) , QLatin1String ( " QtCreator " ) ) ;
2010-10-25 16:57:58 +02:00
ExtensionSystem : : PluginManager pluginManager ;
pluginManager . setFileExtension ( QLatin1String ( " pluginspec " ) ) ;
pluginManager . setSettings ( settings ) ;
locale = settings - > value ( " General/OverrideLanguage " , locale ) . toString ( ) ;
2009-06-10 13:27:05 +02:00
const QString & creatorTrPath = QCoreApplication : : applicationDirPath ( )
+ QLatin1String ( SHARE_PATH " /translations " ) ;
if ( translator . load ( QLatin1String ( " qtcreator_ " ) + locale , creatorTrPath ) ) {
const QString & qtTrPath = QLibraryInfo : : location ( QLibraryInfo : : TranslationsPath ) ;
const QString & qtTrFile = QLatin1String ( " qt_ " ) + locale ;
// Binary installer puts Qt tr files into creatorTrPath
if ( qtTranslator . load ( qtTrFile , qtTrPath ) | | qtTranslator . load ( qtTrFile , creatorTrPath ) ) {
2009-04-20 16:41:06 +02:00
app . installTranslator ( & translator ) ;
app . installTranslator ( & qtTranslator ) ;
app . setProperty ( " qtc_locale " , locale ) ;
} else {
translator . load ( QString ( ) ) ; // unload()
}
}
2010-02-18 17:36:17 +01:00
// Make sure we honor the system's proxy settings
2010-10-21 18:05:15 +02:00
# if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
QUrl proxyUrl ( QString : : fromLatin1 ( qgetenv ( " http_proxy " ) ) ) ;
if ( proxyUrl . isValid ( ) ) {
2011-01-20 12:03:17 +01:00
QNetworkProxy proxy ( QNetworkProxy : : HttpProxy , proxyUrl . host ( ) ,
2010-10-21 18:05:15 +02:00
proxyUrl . port ( ) , proxyUrl . userName ( ) , proxyUrl . password ( ) ) ;
QNetworkProxy : : setApplicationProxy ( proxy ) ;
}
# else
2010-02-18 17:36:17 +01:00
QNetworkProxyFactory : : setUseSystemConfiguration ( true ) ;
2010-10-21 18:05:15 +02:00
# endif
2008-12-02 12:01:29 +01:00
// Load
const QStringList pluginPaths = getPluginPaths ( ) ;
pluginManager . setPluginPaths ( pluginPaths ) ;
2008-12-05 18:29:19 +01:00
QMap < QString , QString > foundAppOptions ;
2008-12-02 12:01:29 +01:00
if ( arguments . size ( ) > 1 ) {
2008-12-05 18:29:19 +01:00
QMap < QString , bool > appOptions ;
2008-12-02 12:01:29 +01:00
appOptions . insert ( QLatin1String ( HELP_OPTION1 ) , false ) ;
appOptions . insert ( QLatin1String ( HELP_OPTION2 ) , false ) ;
appOptions . insert ( QLatin1String ( HELP_OPTION3 ) , false ) ;
appOptions . insert ( QLatin1String ( HELP_OPTION4 ) , false ) ;
appOptions . insert ( QLatin1String ( VERSION_OPTION ) , false ) ;
appOptions . insert ( QLatin1String ( CLIENT_OPTION ) , false ) ;
QString errorMessage ;
if ( ! pluginManager . parseOptions ( arguments ,
appOptions ,
& foundAppOptions ,
& errorMessage ) ) {
displayError ( errorMessage ) ;
printHelp ( QFileInfo ( app . applicationFilePath ( ) ) . baseName ( ) , pluginManager ) ;
return - 1 ;
}
}
const PluginSpecSet plugins = pluginManager . plugins ( ) ;
ExtensionSystem : : PluginSpec * coreplugin = 0 ;
foreach ( ExtensionSystem : : PluginSpec * spec , plugins ) {
if ( spec - > name ( ) = = QLatin1String ( corePluginNameC ) ) {
coreplugin = spec ;
break ;
}
}
if ( ! coreplugin ) {
2009-07-23 17:04:22 +02:00
QString nativePaths = QDir : : toNativeSeparators ( pluginPaths . join ( QLatin1String ( " , " ) ) ) ;
2009-09-29 12:17:37 +02:00
const QString reason = QCoreApplication : : translate ( " Application " , " Could not find 'Core.pluginspec' in %1 " ) . arg ( nativePaths ) ;
2008-12-02 12:01:29 +01:00
displayError ( msgCoreLoadFailure ( reason ) ) ;
return 1 ;
}
if ( coreplugin - > hasError ( ) ) {
displayError ( msgCoreLoadFailure ( coreplugin - > errorString ( ) ) ) ;
return 1 ;
}
if ( foundAppOptions . contains ( QLatin1String ( VERSION_OPTION ) ) ) {
printVersion ( coreplugin , pluginManager ) ;
return 0 ;
}
if ( foundAppOptions . contains ( QLatin1String ( HELP_OPTION1 ) )
| | foundAppOptions . contains ( QLatin1String ( HELP_OPTION2 ) )
| | foundAppOptions . contains ( QLatin1String ( HELP_OPTION3 ) )
| | foundAppOptions . contains ( QLatin1String ( HELP_OPTION4 ) ) ) {
printHelp ( QFileInfo ( app . applicationFilePath ( ) ) . baseName ( ) , pluginManager ) ;
return 0 ;
}
const bool isFirstInstance = ! app . isRunning ( ) ;
2009-12-14 18:01:39 +01:00
if ( ! isFirstInstance & & foundAppOptions . contains ( QLatin1String ( CLIENT_OPTION ) ) ) {
if ( ! app . sendMessage ( pluginManager . serializedArguments ( ) ) ) {
displayError ( msgSendArgumentFailed ( ) ) ;
return - 1 ;
}
return 0 ;
}
2008-12-02 12:01:29 +01:00
pluginManager . loadPlugins ( ) ;
if ( coreplugin - > hasError ( ) ) {
displayError ( msgCoreLoadFailure ( coreplugin - > errorString ( ) ) ) ;
return 1 ;
}
2009-09-29 12:05:03 +02:00
{
QStringList errors ;
foreach ( ExtensionSystem : : PluginSpec * p , pluginManager . plugins ( ) )
2010-04-12 12:50:37 +02:00
// only show errors on startup if plugin is enabled.
2010-05-12 14:34:36 +02:00
if ( p - > hasError ( ) & & p - > isEnabled ( ) & & ! p - > isDisabledIndirectly ( ) )
2010-04-12 12:50:37 +02:00
errors . append ( p - > name ( ) + " \n " + p - > errorString ( ) ) ;
2009-09-29 12:05:03 +02:00
if ( ! errors . isEmpty ( ) )
QMessageBox : : warning ( 0 ,
QCoreApplication : : translate ( " Application " , " Qt Creator - Plugin loader messages " ) ,
errors . join ( QString : : fromLatin1 ( " \n \n " ) ) ) ;
}
2008-12-02 12:01:29 +01:00
if ( isFirstInstance ) {
// Set up lock and remote arguments for the first instance only.
// Silently fallback to unconnected instances for any subsequent
// instances.
app . initialize ( ) ;
2009-12-14 18:01:39 +01:00
QObject : : connect ( & app , SIGNAL ( messageReceived ( QString ) ) ,
& pluginManager , SLOT ( remoteArguments ( QString ) ) ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-14 18:01:39 +01:00
QObject : : connect ( & app , SIGNAL ( fileOpenRequest ( QString ) ) , coreplugin - > plugin ( ) , SLOT ( fileOpenRequest ( QString ) ) ) ;
2008-12-02 12:01:29 +01:00
2010-09-27 14:58:12 +02:00
// shutdown plugin manager on the exit
QObject : : connect ( & app , SIGNAL ( aboutToQuit ( ) ) , & pluginManager , SLOT ( shutdown ( ) ) ) ;
2008-12-02 12:01:29 +01:00
// Do this after the event loop has started
2011-02-16 23:02:52 +01:00
// QTimer::singleShot(100, &pluginManager, SLOT(startTests()));
2010-07-13 13:36:47 +02:00
2010-09-27 14:58:12 +02:00
return app . exec ( ) ;
2008-12-02 12:01:29 +01:00
}
2008-12-16 14:37:23 +01:00