source: trunk/tools/assistant/compat/main.cpp@ 166

Last change on this file since 166 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 16.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the Qt Assistant of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "mainwindow.h"
43#include "helpdialog.h"
44#include "config.h"
45
46#include <QTcpServer>
47#include <QTcpSocket>
48#include <QApplication>
49#include <QPixmap>
50#include <QStringList>
51#include <QDir>
52#include <QMessageBox>
53#include <QPointer>
54#include <QTranslator>
55#include <QLibraryInfo>
56#include <QLocale>
57#include <stdlib.h>
58#include <stdio.h>
59
60#if defined(USE_STATIC_JPEG_PLUGIN)
61 #include <QtPlugin>
62 Q_IMPORT_PLUGIN(qjpeg)
63#endif
64
65#define INDEX_CHECK( text ) if( i+1 >= argc ) { fprintf(stderr, "%s\n", text); return 1; }
66
67QT_BEGIN_NAMESPACE
68
69#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
70QT_BEGIN_INCLUDE_NAMESPACE
71#include <QtDBus/QDBusConnection>
72#include <QtDBus/QDBusAbstractAdaptor>
73#include <QtDBus/QDBusObjectPath>
74#include "tabbedbrowser.h"
75QT_END_INCLUDE_NAMESPACE
76
77class HelpWindowAdaptor : public QDBusAbstractAdaptor
78{
79 Q_OBJECT
80 Q_CLASSINFO("D-Bus Interface", "com.trolltech.Assistant.HelpWindow")
81
82 Q_PROPERTY(QString source READ source WRITE setSource)
83
84public:
85 HelpWindowAdaptor(HelpWindow *w) : QDBusAbstractAdaptor(w), helpWindow(w)
86 {
87 setAutoRelaySignals(true);
88 }
89
90public Q_SLOTS:
91 inline QString source() const { return helpWindow->source().toString(); }
92 inline void setSource(const QString &src) { helpWindow->setSource(src); }
93
94 inline void clearHistory() { helpWindow->clearHistory(); }
95 inline void backward() { helpWindow->backward(); }
96 inline void forward() { helpWindow->forward(); }
97 inline void reload() { helpWindow->reload(); }
98 inline void home() { helpWindow->home(); }
99
100private:
101 HelpWindow *helpWindow;
102};
103
104class AssistantAdaptor : public QDBusAbstractAdaptor
105{
106 Q_OBJECT
107 Q_CLASSINFO("D-Bus Interface", "com.trolltech.Assistant.HelpViewer")
108
109public:
110 AssistantAdaptor(MainWindow *mw) : QDBusAbstractAdaptor(mw), mw(mw)
111 {
112 QDBusConnection connection = QDBusConnection::sessionBus();
113 connection.registerService(QLatin1String("com.trolltech.Assistant"));
114 connection.registerObject(QLatin1String("/Assistant"), mw);
115 }
116
117public slots:
118 void showLink(const QString &link) { mw->showLink(link); }
119 QDBusObjectPath createNewTab();
120 QDBusObjectPath currentTab();
121
122private:
123 QDBusObjectPath pathForBrowser(HelpWindow *window);
124 MainWindow *mw;
125};
126
127QDBusObjectPath AssistantAdaptor::createNewTab()
128{
129 HelpWindow *window = mw->browsers()->newBackgroundTab();
130 return pathForBrowser(window);
131}
132
133QDBusObjectPath AssistantAdaptor::currentTab()
134{
135 HelpWindow *window = mw->browsers()->currentBrowser();
136 return pathForBrowser(window);
137}
138
139QDBusObjectPath AssistantAdaptor::pathForBrowser(HelpWindow *window)
140{
141 int index = mw->browsers()->browsers().indexOf(window);
142 if (index == -1)
143 return QDBusObjectPath();
144
145 QString name(QLatin1String("/Assistant/Tabs/"));
146 name += QString::number(index);
147 QDBusObjectPath path(name);
148
149 if (!window->findChild<HelpWindowAdaptor *>()) {
150 (void)new HelpWindowAdaptor(window);
151 QDBusConnection::sessionBus().registerObject(name, window);
152 }
153
154 return path;
155}
156
157#endif // QT_NO_DBUS
158
159class AssistantSocket : public QTcpSocket
160{
161 Q_OBJECT
162public:
163 AssistantSocket( int sock, QObject *parent = 0 );
164 ~AssistantSocket() {}
165
166signals:
167 void showLinkRequest( const QString& );
168
169private slots:
170 void readClient();
171 void connectionClosed();
172};
173
174
175class AssistantServer : public QTcpServer
176{
177 Q_OBJECT
178public:
179 AssistantServer( QObject* parent = 0 );
180 quint16 getPort() const;
181
182signals:
183 void showLinkRequest( const QString& );
184 void newConnect();
185
186public slots:
187 virtual void incomingConnection( int socket );
188
189private:
190 quint16 p;
191};
192
193AssistantSocket::AssistantSocket( int sock, QObject *parent )
194 : QTcpSocket( parent )
195{
196 connect( this, SIGNAL(readyRead()), SLOT(readClient()) );
197 connect( this, SIGNAL(disconnected()), SLOT(connectionClosed()) );
198 setSocketDescriptor( sock );
199}
200
201void AssistantSocket::readClient()
202{
203 QString link = QString();
204 while ( canReadLine() )
205 link = QLatin1String(readLine());
206 if ( !link.isNull() ) {
207 link = link.replace(QLatin1String("\n"), QLatin1String(""));
208 link = link.replace(QLatin1String("\r"), QLatin1String(""));
209 QFileInfo fi(link);
210 link = fi.absoluteFilePath();
211 emit showLinkRequest( link );
212 }
213}
214
215void AssistantSocket::connectionClosed()
216{
217 deleteLater();
218}
219
220AssistantServer::AssistantServer( QObject *parent )
221 : QTcpServer( parent )
222{
223 listen(QHostAddress::LocalHost, 0);
224 if ( !isListening() ) {
225 QMessageBox::critical( 0, tr( "Qt Assistant" ),
226 tr( "Failed to bind to port %1" ).arg( serverPort() ) );
227 exit( 1 );
228 }
229 p = serverPort();
230}
231
232quint16 AssistantServer::getPort() const
233{
234 return p;
235}
236
237void AssistantServer::incomingConnection( int socket )
238{
239 AssistantSocket *as = new AssistantSocket( socket, this );
240 connect( as, SIGNAL(showLinkRequest(QString)),
241 this, SIGNAL(showLinkRequest(QString)) );
242 emit newConnect();
243}
244
245int runAssistant( int argc, char ** argv )
246{
247 bool withGUI = true;
248#ifndef Q_WS_WIN
249 if ( argc > 1 ) {
250 QString arg = QString::fromLocal8Bit(argv[1]);
251 arg = arg.toLower();
252 if ( arg == QLatin1String("-addcontentfile")
253 || arg == QLatin1String("-removecontentfile")
254 || arg == QLatin1String("-help")
255 || arg == QLatin1String("/?")
256 )
257 withGUI = false;
258 }
259#endif
260 QApplication a(argc, argv, withGUI);
261 a.setOrganizationName(QLatin1String("Trolltech"));
262 a.setApplicationName(QLatin1String("Assistant"));
263
264 QString resourceDir;
265 AssistantServer *as = 0;
266 QStringList catlist;
267 QString file, profileName, aDocPath;
268 bool server = false;
269 bool hideSidebar = false;
270 bool configLoaded = false;
271 if ( argc == 2 ) {
272 file = QString::fromLocal8Bit(argv[1]);
273 if (file.startsWith(QLatin1String("-")) || file == QLatin1String("/?")) {
274 file.clear();
275 } else {
276 QFileInfo fi(file);
277 file = fi.absoluteFilePath();
278 file = MainWindow::urlifyFileName(file);
279 }
280 }
281 if ( file.isEmpty() ) {
282 for ( int i = 1; i < argc; i++ ) {
283 QString opt = QString::fromLocal8Bit(argv[i]).toLower();
284 if ( opt == QLatin1String("-file") ) {
285 INDEX_CHECK( "Missing file argument!" );
286 i++;
287 file = QFile::decodeName(argv[i]);
288 } else if ( opt == QLatin1String("-server") ) {
289 server = true;
290 } else if ( opt == QLatin1String("-profile") ) {
291 INDEX_CHECK( "Missing profile argument!" );
292 profileName = QFile::decodeName(argv[++i]);
293 } else if ( opt == QLatin1String("-addcontentfile") ) {
294 INDEX_CHECK( "Missing content file!" );
295 Config *c = Config::loadConfig(QString());
296 QFileInfo file( QFile::decodeName(argv[i+1]) );
297 if( !file.exists() ) {
298 fprintf(stderr, "Could not locate content file: %s\n", qPrintable(file.absoluteFilePath()));
299 return 1;
300 }
301 DocuParser *parser = DocuParser::createParser( file.absoluteFilePath() );
302 if( parser ) {
303 QFile f( QFile::decodeName(argv[i+1]) );
304 if( !parser->parse( &f ) ) {
305 fprintf(stderr, "Failed to parse file: %s\n", qPrintable(file.absoluteFilePath()));
306 return 1;
307 }
308 parser->addTo( c->profile() );
309 c->setDocRebuild( true );
310 c->save();
311 }
312 return 0;
313 } else if ( opt == QLatin1String("-removecontentfile") ) {
314 INDEX_CHECK("Missing content file!");
315 Config *c = Config::loadConfig(QString());
316 Profile *profile = c->profile();
317 QString contentFile = QString::fromLocal8Bit(argv[i+i]);
318 QStringList entries;
319#ifdef Q_WS_WIN
320 contentFile.replace(QLatin1Char('\\'), QLatin1Char('/'));
321 entries = profile->docs.filter(contentFile, Qt::CaseInsensitive);
322#else
323 entries = profile->docs.filter(contentFile);
324#endif
325 if (entries.count() == 0) {
326 fprintf(stderr, "Could not locate content file: %s\n", qPrintable(contentFile));
327 return 1;
328 } else if (entries.count() > 1) {
329 fprintf(stderr, "More than one entry matching file name found, "
330 "please specify full path to file");
331 return 1;
332 } else {
333 QFileInfo file(entries[0]);
334 if( !file.exists() ) {
335 fprintf(stderr, "Could not locate content file: %s\n", qPrintable(file.absoluteFilePath()));
336 return 1;
337 }
338 profile->removeDocFileEntry( file.absoluteFilePath() );
339 c->setDocRebuild( true );
340 c->save();
341 }
342 return 0;
343 } else if ( QString( QLatin1String(argv[i]) ).toLower() == QLatin1String("-docpath") ) {
344 INDEX_CHECK( "Missing path!" );
345 QDir dir(QString::fromLocal8Bit(argv[i+1]));
346 if ( dir.exists() ) {
347 Config *c = Config::loadConfig(QString());
348 c->saveProfile(Profile::createDefaultProfile(dir.absolutePath()));
349 c->loadDefaultProfile();
350 c->setDocRebuild(true);
351 c->save();
352 configLoaded = true;
353 ++i;
354 } else {
355 fprintf(stderr, "The specified path does not exist!\n");
356 return 1;
357 }
358 } else if ( opt == QLatin1String("-hidesidebar") ) {
359 hideSidebar = true;
360 } else if ( opt == QLatin1String("-help") || opt == QLatin1String("/?") ) {
361 QString helpText = QLatin1String( "Usage: assistant [option]\n"
362 "Options:\n"
363 " -file Filename assistant opens the specified file\n"
364 " -server reads commands from a socket after\n"
365 " assistant has started\n"
366 " -profile fileName starts assistant and displays the\n"
367 " profile specified in the file fileName.\n"
368 " -addContentFile file adds the content file 'file' to the set of\n"
369 " documentation available by default\n"
370 " -removeContentFile file removes the content file 'file' from the\n"
371 " documentation available by default\n"
372 " -docPath path sets the Qt documentation root path to\n"
373 " 'path' and starts assistant\n"
374 " -hideSidebar assistant will hide the sidebar.\n"
375 " -resourceDir assistant will load translations from\n"
376 " this directory.\n"
377 " -help shows this help.");
378#ifdef Q_WS_WIN
379 QMessageBox::information( 0, QLatin1String("Qt Assistant"),
380 QLatin1String("<pre>") + helpText + QLatin1String("</pre>") );
381#else
382 fprintf(stdout, "%s\n", qPrintable(helpText));
383#endif
384 exit( 0 );
385 } else if ( opt == QLatin1String("-resourcedir") ) {
386 INDEX_CHECK( "Missing resource directory argument!" );
387 resourceDir = QFile::decodeName( argv[++i] );
388 } else {
389 fprintf(stderr, "Unrecognized option %s. Try -help to get help.\n", qPrintable(opt));
390 return 1;
391 }
392 }
393 }
394
395 if( resourceDir.isNull() )
396 resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
397
398 QTranslator translator( 0 );
399 translator.load( QLatin1String("assistant_adp_") + QLocale::system().name(), resourceDir );
400 a.installTranslator( &translator );
401
402 QTranslator qtTranslator( 0 );
403 qtTranslator.load( QLatin1String("qt_") + QLocale::system().name(), resourceDir );
404 a.installTranslator( &qtTranslator );
405
406 Config *conf = 0;
407 if (configLoaded)
408 conf = Config::configuration();
409 else
410 conf = Config::loadConfig( profileName );
411 if (!conf) {
412 fprintf( stderr, "Profile '%s' does not exist!\n", profileName.toLatin1().constData() );
413 fflush( stderr );
414 return -1;
415 }
416
417 QStringList links = conf->source();
418 conf->hideSideBar( hideSidebar );
419
420 QPointer<MainWindow> mw = new MainWindow();
421 mw->setObjectName(QLatin1String("Assistant"));
422
423 if ( server ) {
424 as = new AssistantServer();
425 printf("%d\n", as->serverPort() );
426 fflush( stdout );
427 as->connect( as, SIGNAL(showLinkRequest(QString)),
428 mw, SLOT(showLinkFromClient(QString)) );
429 }
430
431#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
432 new AssistantAdaptor(mw);
433#endif // QT_NO_DBUS
434
435 FontSettings settings = conf->fontSettings();
436 if (mw->font() != settings.windowFont)
437 a.setFont(settings.windowFont, "QWidget");
438
439#ifdef Q_WS_MAC
440 // Make sure AssitantClient shows the window in front.
441 mw->raise();
442#endif
443 mw->show();
444
445 if (!file.isEmpty())
446 mw->showLink( MainWindow::urlifyFileName(file) );
447 else if (file.isEmpty())
448 mw->showLinks( links );
449
450 a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );
451
452 int appExec = a.exec();
453 delete (MainWindow*)mw;
454 return appExec;
455}
456
457QT_END_NAMESPACE
458
459int main( int argc, char ** argv )
460{
461 Q_INIT_RESOURCE(assistant);
462 return QT_PREPEND_NAMESPACE(runAssistant)(argc, argv);
463}
464
465#include "main.moc"
Note: See TracBrowser for help on using the repository browser.