tools/assistant/main.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the Qt Assistant of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "mainwindow.h"
00025 #include "helpdialog.h"
00026 #include "config.h"
00027 
00028 #include <QTcpServer>
00029 #include <QTcpSocket>
00030 #include <QApplication>
00031 #include <QPixmap>
00032 #include <QStringList>
00033 #include <QDir>
00034 #include <QMessageBox>
00035 #include <QPointer>
00036 #include <QTranslator>
00037 #include <QLibraryInfo>
00038 #include <QLocale>
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041 
00042 #if defined(USE_STATIC_JPEG_PLUGIN)
00043   #include <QtPlugin>
00044   Q_IMPORT_PLUGIN(qjpeg)
00045 #endif
00046 
00047 #define INDEX_CHECK( text ) if( i+1 >= argc ) { fprintf(stderr, "%s\n", text); return 1; }
00048 
00049 
00050 #if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
00051 #include <QtDBus/QDBusConnection>
00052 #include <QtDBus/QDBusAbstractAdaptor>
00053 
00054 class AssistantAdaptor : public QDBusAbstractAdaptor
00055 {
00056     Q_OBJECT
00057     Q_CLASSINFO("D-Bus Interface", "com.trolltech.Assistant.HelpViewer")
00058 
00059 public:
00060     AssistantAdaptor(MainWindow *mw) : QDBusAbstractAdaptor(mw), mw(mw)
00061     {
00062         QDBusConnection connection = QDBusConnection::sessionBus();
00063         connection.registerService("com.trolltech.Assistant");
00064         connection.registerObject("/Assistant", mw);
00065     }
00066 
00067 public slots:
00068     void showLink(const QString &link) { mw->showLink(link); }
00069 
00070 private:
00071     MainWindow *mw;
00072 };
00073 #endif // QT_NO_DBUS
00074 
00075 class AssistantSocket : public QTcpSocket
00076 {
00077     Q_OBJECT
00078 public:
00079     AssistantSocket( int sock, QObject *parent = 0 );
00080     ~AssistantSocket() {}
00081 
00082 signals:
00083     void showLinkRequest( const QString& );
00084 
00085 private slots:
00086     void readClient();
00087     void connectionClosed();
00088 };
00089 
00090 
00091 class AssistantServer : public QTcpServer
00092 {
00093     Q_OBJECT
00094 public:
00095     AssistantServer( QObject* parent = 0 );
00096     quint16 getPort() const;
00097 
00098 signals:
00099     void showLinkRequest( const QString& );
00100     void newConnect();
00101 
00102 public slots:
00103     virtual void incomingConnection( int socket );
00104 
00105 private:
00106     quint16 p;
00107 };
00108 
00109 AssistantSocket::AssistantSocket( int sock, QObject *parent )
00110     : QTcpSocket( parent )
00111 {
00112     connect( this, SIGNAL(readyRead()), SLOT(readClient()) );
00113     connect( this, SIGNAL(disconnected()), SLOT(connectionClosed()) );
00114     setSocketDescriptor( sock );
00115 }
00116 
00117 void AssistantSocket::readClient()
00118 {
00119     QString link = QString();
00120     while ( canReadLine() )
00121         link = readLine();
00122     if ( !link.isNull() ) {
00123         link = link.replace(QLatin1String("\n"), QLatin1String(""));
00124         link = link.replace(QLatin1String("\r"), QLatin1String(""));
00125         QFileInfo fi(link);
00126         link = fi.absoluteFilePath();
00127         emit showLinkRequest( link );
00128     }
00129 }
00130 
00131 void AssistantSocket::connectionClosed()
00132 {
00133     deleteLater();
00134 }
00135 
00136 AssistantServer::AssistantServer( QObject *parent )
00137     : QTcpServer( parent )
00138 {
00139     listen(QHostAddress::LocalHost, 0);
00140     if ( !isListening() ) {
00141         QMessageBox::critical( 0, tr( "Qt Assistant" ),
00142                 tr( "Failed to bind to port %1" ).arg( serverPort() ) );
00143         exit( 1 );
00144     }
00145     p = serverPort();
00146 }
00147 
00148 quint16 AssistantServer::getPort() const
00149 {
00150     return p;
00151 }
00152 
00153 void AssistantServer::incomingConnection( int socket )
00154 {
00155     AssistantSocket *as = new AssistantSocket( socket, this );
00156     connect( as, SIGNAL(showLinkRequest(QString)),
00157              this, SIGNAL(showLinkRequest(QString)) );
00158     emit newConnect();
00159 }
00160 
00161 int main( int argc, char ** argv )
00162 {
00163     Q_INIT_RESOURCE(assistant);
00164 
00165     bool withGUI = true;
00166 #ifndef Q_WS_WIN
00167     if ( argc > 1 ) {
00168         QString arg = QString::fromLocal8Bit(argv[1]);
00169         arg = arg.toLower();
00170         if ( arg == QLatin1String("-addcontentfile")
00171             || arg == QLatin1String("-removecontentfile")
00172             || arg == QLatin1String("-help")
00173             || arg == QLatin1String("/?")
00174             )
00175             withGUI = false;
00176     }
00177 #endif
00178     QApplication a(argc, argv, withGUI);
00179     a.setOrganizationName("Trolltech");
00180     a.setApplicationName("Assistant");
00181 
00182     QString resourceDir;
00183     AssistantServer *as = 0;
00184     QStringList catlist;
00185     QString file, profileName, aDocPath;
00186     bool server = false;
00187     bool hideSidebar = false;
00188     if ( argc == 2 ) {
00189         file = QString::fromLocal8Bit(argv[1]);
00190         if (file.startsWith(QLatin1String("-")) || file == QLatin1String("/?")) {
00191             file.clear();
00192         } else {
00193             QFileInfo fi(file);
00194             file = fi.absoluteFilePath();
00195             file = MainWindow::urlifyFileName(file);
00196         }
00197     }
00198     if ( file.isEmpty() ) {
00199         for ( int i = 1; i < argc; i++ ) {
00200             QString opt = QString::fromLocal8Bit(argv[i]).toLower();
00201             if ( opt == QLatin1String("-file") ) {
00202                 INDEX_CHECK( "Missing file argument!" );
00203                 i++;
00204                 file = QFile::decodeName(argv[i]);
00205             } else if ( opt == QLatin1String("-server") ) {
00206                 server = true;
00207             } else if ( opt == QLatin1String("-profile") ) {
00208                 INDEX_CHECK( "Missing profile argument!" );
00209                 profileName = QFile::decodeName(argv[++i]);
00210             } else if ( opt == QLatin1String("-addcontentfile") ) {
00211                 INDEX_CHECK( "Missing content file!" );
00212                 Config *c = Config::loadConfig(QString());
00213                 QFileInfo file( QFile::decodeName(argv[i+1]) );
00214                 if( !file.exists() ) {
00215                     fprintf(stderr, "Could not locate content file: %s\n", qPrintable(file.absoluteFilePath()));
00216                     return 1;
00217                 }
00218                 DocuParser *parser = DocuParser::createParser( file.absoluteFilePath() );
00219                 if( parser ) {
00220                     QFile f( QFile::decodeName(argv[i+1]) );
00221                     if( !parser->parse( &f ) ) {
00222                         fprintf(stderr, "Failed to parse file: %s\n", qPrintable(file.absoluteFilePath()));
00223                         return 1;
00224                     }
00225                     parser->addTo( c->profile() );
00226                     c->setDocRebuild( true );
00227                     c->save();
00228                 }
00229                 return 0;
00230             } else if ( opt == QLatin1String("-removecontentfile") ) {
00231                 INDEX_CHECK("Missing content file!");
00232                 Config *c = Config::loadConfig(QString());
00233                 Profile *profile = c->profile();
00234                 QString contentFile = QString::fromLocal8Bit(argv[i+i]);
00235                 QStringList entries;
00236 #ifdef Q_WS_WIN
00237                 contentFile.replace('\\', '/');
00238                 entries = profile->docs.filter(contentFile, Qt::CaseInsensitive);
00239 #else
00240                 entries = profile->docs.filter(contentFile);
00241 #endif
00242                 if (entries.count() == 0) {
00243                     fprintf(stderr, "Could not locate content file: %s\n", qPrintable(contentFile));
00244                     return 1;
00245                 } else if (entries.count() > 1) {
00246                     fprintf(stderr, "More than one entry matching file name found, "
00247                         "please specify full path to file");
00248                     return 1;
00249                 } else {
00250                     QFileInfo file(entries[0]);
00251                     if( !file.exists() ) {
00252                         fprintf(stderr, "Could not locate content file: %s\n", qPrintable(file.absoluteFilePath()));
00253                         return 1;
00254                     }
00255                     profile->removeDocFileEntry( file.absoluteFilePath() );
00256                     c->setDocRebuild( true );
00257                     c->save();
00258                 }
00259                 return 0;
00260             } else if ( QString( argv[i] ).toLower() == "-docpath" ) {
00261                 INDEX_CHECK( "Missing path!" );
00262                 QDir dir(QString::fromLocal8Bit(argv[i+1]));
00263                 if ( dir.exists() ) {
00264                     Config *c = Config::loadConfig(QString());
00265                     c->saveProfile(Profile::createDefaultProfile(dir.absolutePath()));
00266                     c->loadDefaultProfile();
00267                     c->setDocRebuild(true);
00268                     c->save();
00269                 } else {
00270                     fprintf(stderr, "The specified path does not exist!\n");
00271                     return 1;
00272                 }
00273             } else if ( opt == QLatin1String("-hidesidebar") ) {
00274                 hideSidebar = true;
00275             } else if ( opt == QLatin1String("-help") || opt == QLatin1String("/?") ) {
00276                 QString helpText = QLatin1String( "Usage: assistant [option]\n"
00277                                   "Options:\n"
00278                                   " -file Filename             assistant opens the specified file\n"
00279                                   " -server                    reads commands from a socket after\n"
00280                                   "                            assistant has started\n"
00281                                   " -profile fileName          starts assistant and displays the\n"
00282                                   "                            profile specified in the file fileName.\n"
00283                                   " -addContentFile file       adds the content file 'file' to the set of\n"
00284                                   "                            documentation available by default\n"
00285                                   " -removeContentFile file    removes the content file 'file' from the\n"
00286                                   "                            documentation available by default\n"
00287                                   " -docPath path              sets the Qt documentation root path to\n"
00288                                   "                            'path' and starts assistant\n"
00289                                   " -hideSidebar               assistant will hide the sidebar.\n"
00290                                   " -resourceDir               assistant will load translations from\n"
00291                                   "                            this directory.\n"
00292                                   " -help                      shows this help.");
00293 #ifdef Q_WS_WIN
00294                 QMessageBox::information( 0, QLatin1String("Qt Assistant"),
00295                     QLatin1String("<pre>") + helpText + QLatin1String("</pre>") );
00296 #else
00297                 fprintf(stdout, "%s\n", qPrintable(helpText));
00298 #endif
00299                 exit( 0 );
00300             } else if ( opt == QLatin1String("-resourcedir") ) {
00301                 INDEX_CHECK( "Missing resource directory argument!" );
00302                 resourceDir = QFile::decodeName( argv[++i] );
00303             } else {
00304                 fprintf(stderr, "Unrecognized option %s. Try -help to get help.\n", qPrintable(opt));
00305             }
00306         }
00307     }
00308 
00309     if( resourceDir.isNull() )
00310         resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
00311 
00312     QTranslator translator( 0 );
00313     translator.load( QLatin1String("assistant_") + QLocale::system().name(), resourceDir );
00314     a.installTranslator( &translator );
00315 
00316     QTranslator qtTranslator( 0 );
00317     qtTranslator.load( QLatin1String("qt_") + QLocale::system().name(), resourceDir );
00318     a.installTranslator( &qtTranslator );
00319 
00320     Config *conf = Config::loadConfig( profileName );
00321     if ( !conf ) {
00322         fprintf( stderr, "Profile '%s' does not exist!\n", profileName.toLatin1().constData() );
00323         fflush( stderr );
00324         return -1;
00325     }
00326 
00327     QStringList links = conf->source();
00328     conf->hideSideBar( hideSidebar );
00329 
00330     QPointer<MainWindow> mw = new MainWindow();
00331     mw->setObjectName(QLatin1String("Assistant"));
00332 
00333     if ( server ) {
00334         as = new AssistantServer();
00335         printf("%d\n", as->serverPort() );
00336         fflush( stdout );
00337         as->connect( as, SIGNAL(showLinkRequest(QString)),
00338                      mw, SLOT(showLinkFromClient(QString)) );
00339     }
00340 
00341 #if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
00342     new AssistantAdaptor(mw);
00343 #endif // QT_NO_DBUS
00344 
00345     mw->show();
00346 
00347     if ( !file.isEmpty() ) {
00348         mw->showLink( MainWindow::urlifyFileName(file) );
00349     } else if ( file.isEmpty() )
00350         mw->showLinks( links );
00351 
00352     a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );
00353 
00354     int appExec = a.exec();
00355     delete (MainWindow*)mw;
00356     return appExec;
00357 }
00358 
00359 #include "main.moc"

Generated on Thu Mar 15 11:57:32 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1