| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the Qt Assistant of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** 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. |
| ** |
| ** 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. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| #include "tracer.h" |
| |
| #include "remotecontrol.h" |
| #include "mainwindow.h" |
| #include "centralwidget.h" |
| #include "helpenginewrapper.h" |
| |
| #include <QtCore/QFile> |
| #include <QtCore/QFileInfo> |
| #include <QtCore/QFileSystemWatcher> |
| #include <QtCore/QThread> |
| #include <QtCore/QTextStream> |
| #include <QtCore/QSocketNotifier> |
| |
| #include <QtGui/QMessageBox> |
| #include <QtGui/QApplication> |
| |
| #include <QtHelp/QHelpEngine> |
| #include <QtHelp/QHelpIndexWidget> |
| |
| #ifdef Q_OS_WIN |
| # include "remotecontrol_win.h" |
| #endif |
| |
| QT_BEGIN_NAMESPACE |
| |
| #ifdef Q_OS_WIN |
| |
| StdInListenerWin::StdInListenerWin(QObject *parent) |
| : QThread(parent) |
| { |
| TRACE_OBJ |
| } |
| |
| StdInListenerWin::~StdInListenerWin() |
| { |
| TRACE_OBJ |
| terminate(); |
| wait(); |
| } |
| |
| void StdInListenerWin::run() |
| { |
| TRACE_OBJ |
| bool ok = true; |
| char chBuf[4096]; |
| DWORD dwRead; |
| |
| #ifndef Q_WS_WINCE |
| HANDLE hStdin, hStdinDup; |
| |
| hStdin = GetStdHandle(STD_INPUT_HANDLE); |
| if (hStdin == INVALID_HANDLE_VALUE) |
| return; |
| |
| DuplicateHandle(GetCurrentProcess(), hStdin, |
| GetCurrentProcess(), &hStdinDup, |
| 0, false, DUPLICATE_SAME_ACCESS); |
| |
| CloseHandle(hStdin); |
| #else |
| HANDLE hStdinDup; |
| hStdinDup = stdin; |
| #endif |
| |
| while (ok) { |
| ok = ReadFile(hStdinDup, chBuf, sizeof(chBuf), &dwRead, NULL); |
| if (ok && dwRead != 0) |
| emit receivedCommand(QString::fromLocal8Bit(chBuf, dwRead)); |
| } |
| } |
| #endif |
| |
| RemoteControl::RemoteControl(MainWindow *mainWindow) |
| : QObject(mainWindow) |
| , m_mainWindow(mainWindow) |
| , m_debug(false) |
| , m_caching(true) |
| , m_syncContents(false) |
| , m_expandTOC(-2) |
| , helpEngine(HelpEngineWrapper::instance()) |
| |
| { |
| TRACE_OBJ |
| connect(m_mainWindow, SIGNAL(initDone()), this, SLOT(applyCache())); |
| #ifdef Q_OS_WIN |
| StdInListenerWin *l = new StdInListenerWin(this); |
| connect(l, SIGNAL(receivedCommand(QString)), |
| this, SLOT(handleCommandString(QString))); |
| l->start(); |
| #else |
| QSocketNotifier *notifier = new QSocketNotifier(fileno(stdin), |
| QSocketNotifier::Read, this); |
| connect(notifier, SIGNAL(activated(int)), this, SLOT(receivedData())); |
| notifier->setEnabled(true); |
| #endif |
| } |
| |
| void RemoteControl::receivedData() |
| { |
| TRACE_OBJ |
| QByteArray ba; |
| while (true) { |
| char c = getc(stdin); |
| if (c == EOF || c == '\0') |
| break; |
| if (c) |
| ba.append(c); |
| if (c == '\n') |
| break; |
| } |
| handleCommandString(QString::fromLocal8Bit(ba)); |
| } |
| |
| void RemoteControl::handleCommandString(const QString &cmdString) |
| { |
| TRACE_OBJ |
| QStringList cmds = cmdString.split(QLatin1Char(';')); |
| QStringList::const_iterator it = cmds.constBegin(); |
| while (it != cmds.constEnd()) { |
| QString cmd, arg; |
| splitInputString(*it, cmd, arg); |
| |
| if (m_debug) |
| QMessageBox::information(0, tr("Debugging Remote Control"), |
| tr("Received Command: %1 %2").arg(cmd).arg(arg)); |
| |
| if (cmd == QLatin1String("debug")) |
| handleDebugCommand(arg); |
| else if (cmd == QLatin1String("show")) |
| handleShowOrHideCommand(arg, true); |
| else if (cmd == QLatin1String("hide")) |
| handleShowOrHideCommand(arg, false); |
| else if (cmd == QLatin1String("setsource")) |
| handleSetSourceCommand(arg); |
| else if (cmd == QLatin1String("synccontents")) |
| handleSyncContentsCommand(); |
| else if (cmd == QLatin1String("activatekeyword")) |
| handleActivateKeywordCommand(arg); |
| else if (cmd == QLatin1String("activateidentifier")) |
| handleActivateIdentifierCommand(arg); |
| else if (cmd == QLatin1String("expandtoc")) |
| handleExpandTocCommand(arg); |
| else if (cmd == QLatin1String("setcurrentfilter")) |
| handleSetCurrentFilterCommand(arg); |
| else if (cmd == QLatin1String("register")) |
| handleRegisterCommand(arg); |
| else if (cmd == QLatin1String("unregister")) |
| handleUnregisterCommand(arg); |
| else |
| return; |
| |
| ++it; |
| } |
| m_mainWindow->raise(); |
| m_mainWindow->activateWindow(); |
| } |
| |
| void RemoteControl::splitInputString(const QString &input, QString &cmd, |
| QString &arg) |
| { |
| TRACE_OBJ |
| QString cmdLine = input.trimmed(); |
| int i = cmdLine.indexOf(QLatin1Char(' ')); |
| cmd = cmdLine.left(i); |
| arg = cmdLine.mid(i+1); |
| cmd = cmd.toLower(); |
| } |
| |
| void RemoteControl::handleDebugCommand(const QString &arg) |
| { |
| TRACE_OBJ |
| m_debug = arg == QLatin1String("on"); |
| } |
| |
| void RemoteControl::handleShowOrHideCommand(const QString &arg, bool show) |
| { |
| TRACE_OBJ |
| if (arg.toLower() == QLatin1String("contents")) |
| m_mainWindow->setContentsVisible(show); |
| else if (arg.toLower() == QLatin1String("index")) |
| m_mainWindow->setIndexVisible(show); |
| else if (arg.toLower() == QLatin1String("bookmarks")) |
| m_mainWindow->setBookmarksVisible(show); |
| else if (arg.toLower() == QLatin1String("search")) |
| m_mainWindow->setSearchVisible(show); |
| } |
| |
| void RemoteControl::handleSetSourceCommand(const QString &arg) |
| { |
| TRACE_OBJ |
| QUrl url(arg); |
| if (url.isValid()) { |
| if (url.isRelative()) |
| url = CentralWidget::instance()->currentSource().resolved(url); |
| if (m_caching) { |
| clearCache(); |
| m_setSource = url; |
| } else { |
| CentralWidget::instance()->setSource(url); |
| } |
| } |
| } |
| |
| void RemoteControl::handleSyncContentsCommand() |
| { |
| TRACE_OBJ |
| if (m_caching) |
| m_syncContents = true; |
| else |
| m_mainWindow->syncContents(); |
| } |
| |
| void RemoteControl::handleActivateKeywordCommand(const QString &arg) |
| { |
| TRACE_OBJ |
| if (m_caching) { |
| clearCache(); |
| m_activateKeyword = arg; |
| } else { |
| m_mainWindow->setIndexString(arg); |
| if (!arg.isEmpty()) |
| helpEngine.indexWidget()->activateCurrentItem(); |
| } |
| } |
| |
| void RemoteControl::handleActivateIdentifierCommand(const QString &arg) |
| { |
| TRACE_OBJ |
| if (m_caching) { |
| clearCache(); |
| m_activateIdentifier = arg; |
| } else { |
| const QMap<QString, QUrl> &links = helpEngine.linksForIdentifier(arg); |
| if (!links.isEmpty()) |
| CentralWidget::instance()->setSource(links.constBegin().value()); |
| } |
| } |
| |
| void RemoteControl::handleExpandTocCommand(const QString &arg) |
| { |
| TRACE_OBJ |
| bool ok = false; |
| int depth = -2; |
| if (!arg.isEmpty()) |
| depth = arg.toInt(&ok); |
| if (!ok || depth < -2) |
| depth = -2; |
| |
| if (m_caching) |
| m_expandTOC = depth; |
| else if (depth != -2) |
| m_mainWindow->expandTOC(depth); |
| } |
| |
| void RemoteControl::handleSetCurrentFilterCommand(const QString &arg) |
| { |
| TRACE_OBJ |
| if (helpEngine.customFilters().contains(arg)) { |
| if (m_caching) { |
| clearCache(); |
| m_currentFilter = arg; |
| } else { |
| helpEngine.setCurrentFilter(arg); |
| } |
| } |
| } |
| |
| void RemoteControl::handleRegisterCommand(const QString &arg) |
| { |
| TRACE_OBJ |
| const QString &absFileName = QFileInfo(arg).absoluteFilePath(); |
| if (helpEngine.registeredDocumentations(). |
| contains(QHelpEngineCore::namespaceName(absFileName))) |
| return; |
| if (helpEngine.registerDocumentation(absFileName)) |
| helpEngine.setupData(); |
| } |
| |
| void RemoteControl::handleUnregisterCommand(const QString &arg) |
| { |
| TRACE_OBJ |
| const QString &absFileName = QFileInfo(arg).absoluteFilePath(); |
| const QString &ns = QHelpEngineCore::namespaceName(absFileName); |
| if (helpEngine.registeredDocumentations().contains(ns)) { |
| CentralWidget* widget = CentralWidget::instance(); |
| widget->closeOrReloadTabs(widget->currentSourceFileList().keys(ns), false); |
| if (helpEngine.unregisterDocumentation(ns)) |
| helpEngine.setupData(); |
| } |
| } |
| |
| void RemoteControl::applyCache() |
| { |
| TRACE_OBJ |
| if (m_setSource.isValid()) { |
| CentralWidget::instance()->setSource(m_setSource); |
| } else if (!m_activateKeyword.isEmpty()) { |
| m_mainWindow->setIndexString(m_activateKeyword); |
| helpEngine.indexWidget()->activateCurrentItem(); |
| } else if (!m_activateIdentifier.isEmpty()) { |
| QMap<QString, QUrl> links = |
| helpEngine.linksForIdentifier(m_activateIdentifier); |
| if (!links.isEmpty()) |
| CentralWidget::instance()->setSource(links.constBegin().value()); |
| } else if (!m_currentFilter.isEmpty()) { |
| helpEngine.setCurrentFilter(m_currentFilter); |
| } |
| |
| if (m_syncContents) |
| m_mainWindow->syncContents(); |
| |
| Q_ASSERT(m_expandTOC >= -2); |
| if (m_expandTOC != -2) |
| m_mainWindow->expandTOC(m_expandTOC); |
| |
| m_caching = false; |
| } |
| |
| void RemoteControl::clearCache() |
| { |
| TRACE_OBJ |
| m_currentFilter.clear(); |
| m_setSource.clear(); |
| m_syncContents = false; |
| m_activateKeyword.clear(); |
| m_activateIdentifier.clear(); |
| } |
| |
| QT_END_NAMESPACE |