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 |
|
---|
67 | QT_BEGIN_NAMESPACE
|
---|
68 |
|
---|
69 | #if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
|
---|
70 | QT_BEGIN_INCLUDE_NAMESPACE
|
---|
71 | #include <QtDBus/QDBusConnection>
|
---|
72 | #include <QtDBus/QDBusAbstractAdaptor>
|
---|
73 | #include <QtDBus/QDBusObjectPath>
|
---|
74 | #include "tabbedbrowser.h"
|
---|
75 | QT_END_INCLUDE_NAMESPACE
|
---|
76 |
|
---|
77 | class 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 |
|
---|
84 | public:
|
---|
85 | HelpWindowAdaptor(HelpWindow *w) : QDBusAbstractAdaptor(w), helpWindow(w)
|
---|
86 | {
|
---|
87 | setAutoRelaySignals(true);
|
---|
88 | }
|
---|
89 |
|
---|
90 | public 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 |
|
---|
100 | private:
|
---|
101 | HelpWindow *helpWindow;
|
---|
102 | };
|
---|
103 |
|
---|
104 | class AssistantAdaptor : public QDBusAbstractAdaptor
|
---|
105 | {
|
---|
106 | Q_OBJECT
|
---|
107 | Q_CLASSINFO("D-Bus Interface", "com.trolltech.Assistant.HelpViewer")
|
---|
108 |
|
---|
109 | public:
|
---|
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 |
|
---|
117 | public slots:
|
---|
118 | void showLink(const QString &link) { mw->showLink(link); }
|
---|
119 | QDBusObjectPath createNewTab();
|
---|
120 | QDBusObjectPath currentTab();
|
---|
121 |
|
---|
122 | private:
|
---|
123 | QDBusObjectPath pathForBrowser(HelpWindow *window);
|
---|
124 | MainWindow *mw;
|
---|
125 | };
|
---|
126 |
|
---|
127 | QDBusObjectPath AssistantAdaptor::createNewTab()
|
---|
128 | {
|
---|
129 | HelpWindow *window = mw->browsers()->newBackgroundTab();
|
---|
130 | return pathForBrowser(window);
|
---|
131 | }
|
---|
132 |
|
---|
133 | QDBusObjectPath AssistantAdaptor::currentTab()
|
---|
134 | {
|
---|
135 | HelpWindow *window = mw->browsers()->currentBrowser();
|
---|
136 | return pathForBrowser(window);
|
---|
137 | }
|
---|
138 |
|
---|
139 | QDBusObjectPath 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 |
|
---|
159 | class AssistantSocket : public QTcpSocket
|
---|
160 | {
|
---|
161 | Q_OBJECT
|
---|
162 | public:
|
---|
163 | AssistantSocket( int sock, QObject *parent = 0 );
|
---|
164 | ~AssistantSocket() {}
|
---|
165 |
|
---|
166 | signals:
|
---|
167 | void showLinkRequest( const QString& );
|
---|
168 |
|
---|
169 | private slots:
|
---|
170 | void readClient();
|
---|
171 | void connectionClosed();
|
---|
172 | };
|
---|
173 |
|
---|
174 |
|
---|
175 | class AssistantServer : public QTcpServer
|
---|
176 | {
|
---|
177 | Q_OBJECT
|
---|
178 | public:
|
---|
179 | AssistantServer( QObject* parent = 0 );
|
---|
180 | quint16 getPort() const;
|
---|
181 |
|
---|
182 | signals:
|
---|
183 | void showLinkRequest( const QString& );
|
---|
184 | void newConnect();
|
---|
185 |
|
---|
186 | public slots:
|
---|
187 | virtual void incomingConnection( int socket );
|
---|
188 |
|
---|
189 | private:
|
---|
190 | quint16 p;
|
---|
191 | };
|
---|
192 |
|
---|
193 | AssistantSocket::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 |
|
---|
201 | void 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 |
|
---|
215 | void AssistantSocket::connectionClosed()
|
---|
216 | {
|
---|
217 | deleteLater();
|
---|
218 | }
|
---|
219 |
|
---|
220 | AssistantServer::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 |
|
---|
232 | quint16 AssistantServer::getPort() const
|
---|
233 | {
|
---|
234 | return p;
|
---|
235 | }
|
---|
236 |
|
---|
237 | void 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 |
|
---|
245 | int 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 |
|
---|
457 | QT_END_NAMESPACE
|
---|
458 |
|
---|
459 | int 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"
|
---|