Changeset View
Changeset View
Standalone View
Standalone View
plugins/qthelp/qthelpproviderabstract.cpp
Show All 17 Lines | 1 | /* This file is part of KDevelop | |||
---|---|---|---|---|---|
18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
19 | Boston, MA 02110-1301, USA. | 19 | Boston, MA 02110-1301, USA. | ||
20 | */ | 20 | */ | ||
21 | 21 | | |||
22 | #include "qthelpprovider.h" | 22 | #include "qthelpprovider.h" | ||
23 | 23 | | |||
24 | #include <QHelpIndexModel> | 24 | #include <QHelpIndexModel> | ||
25 | #include <QHelpContentModel> | 25 | #include <QHelpContentModel> | ||
26 | #include <QHelpSearchEngine> | ||||
26 | 27 | | |||
27 | #include <QStandardPaths> | 28 | #include <QStandardPaths> | ||
28 | 29 | | |||
30 | #include <QString> | ||||
31 | #include <QProcess> | ||||
32 | #include <QApplication> | ||||
33 | | ||||
29 | #include <language/duchain/duchain.h> | 34 | #include <language/duchain/duchain.h> | ||
30 | #include <language/duchain/declaration.h> | 35 | #include <language/duchain/declaration.h> | ||
31 | #include <language/duchain/duchainlock.h> | 36 | #include <language/duchain/duchainlock.h> | ||
32 | #include <language/duchain/parsingenvironment.h> | 37 | #include <language/duchain/parsingenvironment.h> | ||
33 | 38 | | |||
34 | #include "qthelpnetwork.h" | 39 | #include "qthelpnetwork.h" | ||
35 | #include "qthelpdocumentation.h" | 40 | #include "qthelpdocumentation.h" | ||
36 | #include "debug.h" | 41 | #include "debug.h" | ||
37 | 42 | | |||
38 | using namespace KDevelop; | 43 | using namespace KDevelop; | ||
39 | 44 | | |||
45 | // subclass QProcess so we can be our own exit watchdog | ||||
46 | class ExternalViewerProcess : public QProcess | ||||
47 | { | ||||
48 | Q_OBJECT | ||||
49 | public: | ||||
50 | ExternalViewerProcess(QObject* parent); | ||||
51 | ~ExternalViewerProcess() | ||||
52 | { | ||||
53 | #ifdef Q_OS_UNIX | ||||
54 | qint64 pid = processId(); | ||||
55 | if (pid > 0) { | ||||
56 | QProcess *hup = new QProcess(this); | ||||
57 | hup->startDetached(QString::fromLatin1("kill -1 %1").arg(pid)); | ||||
58 | hup->waitForFinished(500); | ||||
59 | } | ||||
60 | QProcess::waitForFinished(500); | ||||
61 | #endif | ||||
62 | } | ||||
63 | public Q_SLOTS: | ||||
64 | void externalViewerExit(int exitCode, QProcess::ExitStatus exitStatus); | ||||
65 | }; | ||||
66 | | ||||
67 | ExternalViewerProcess* QtHelpProviderAbstract::m_externalViewerProcess = Q_NULLPTR; | ||||
68 | bool QtHelpProviderAbstract::s_useExternalViewer = false; | ||||
69 | | ||||
70 | ExternalViewerProcess::ExternalViewerProcess(QObject *parent) | ||||
71 | : QProcess(parent) | ||||
72 | { | ||||
73 | connect(this, static_cast<void(ExternalViewerProcess::*)(int, QProcess::ExitStatus)>(&ExternalViewerProcess::finished), | ||||
74 | &ExternalViewerProcess::externalViewerExit); | ||||
75 | } | ||||
76 | | ||||
77 | void ExternalViewerProcess::externalViewerExit(int exitCode, QProcess::ExitStatus exitStatus) | ||||
78 | { | ||||
79 | if (this == QtHelpProviderAbstract::m_externalViewerProcess) { | ||||
80 | qCDebug(QTHELP) << Q_FUNC_INFO << "externalViewer" << this << "has exited with code" | ||||
81 | << exitCode << "and status" << exitStatus; | ||||
82 | deleteLater(); | ||||
83 | QtHelpProviderAbstract::m_externalViewerProcess = Q_NULLPTR; | ||||
84 | } | ||||
85 | } | ||||
86 | | ||||
40 | QtHelpProviderAbstract::QtHelpProviderAbstract(QObject *parent, const QString &collectionFileName, const QVariantList &args) | 87 | QtHelpProviderAbstract::QtHelpProviderAbstract(QObject *parent, const QString &collectionFileName, const QVariantList &args) | ||
41 | : QObject(parent) | 88 | : QObject(parent) | ||
42 | , m_engine(QStandardPaths::writableLocation(QStandardPaths::DataLocation)+'/'+collectionFileName) | 89 | , m_engine(QStandardPaths::writableLocation(QStandardPaths::DataLocation)+'/'+collectionFileName) | ||
43 | , m_nam(new HelpNetworkAccessManager(&m_engine, this)) | 90 | , m_nam(new HelpNetworkAccessManager(&m_engine, this)) | ||
44 | { | 91 | { | ||
45 | Q_UNUSED(args); | 92 | Q_UNUSED(args); | ||
46 | if( !m_engine.setupData() ) { | 93 | if( !m_engine.setupData() ) { | ||
47 | qCWarning(QTHELP) << "Couldn't setup QtHelp Collection file"; | 94 | qCWarning(QTHELP) << "Couldn't setup QtHelp Collection file"; | ||
48 | } | 95 | } | ||
96 | s_useExternalViewer = false; | ||||
49 | } | 97 | } | ||
50 | 98 | | |||
51 | | ||||
52 | QtHelpProviderAbstract::~QtHelpProviderAbstract() | 99 | QtHelpProviderAbstract::~QtHelpProviderAbstract() | ||
53 | { | 100 | { | ||
54 | } | 101 | } | ||
55 | 102 | | |||
103 | void QtHelpProviderAbstract::setUseExternalViewer(const bool extViewer) | ||||
104 | { | ||||
105 | s_useExternalViewer = extViewer; | ||||
106 | } | ||||
107 | | ||||
108 | ExternalViewerProcess* QtHelpProviderAbstract::externalViewer() const | ||||
109 | { | ||||
110 | // turning off the use of an external help viewer shouldn't terminate | ||||
111 | // an already running viewer process, we just stop using it. | ||||
112 | if (!s_useExternalViewer) { | ||||
113 | return Q_NULLPTR; | ||||
114 | } | ||||
115 | if (!m_externalViewerProcess) { | ||||
116 | m_externalViewerProcess = new ExternalViewerProcess(qApp); | ||||
117 | QStringList args = {"-enableRemoteControl"}; | ||||
118 | m_externalViewerProcess->start(QStandardPaths::findExecutable(QLatin1String("kdevelop-qthelp-viewer")), | ||||
119 | args, QIODevice::WriteOnly|QIODevice::Append); | ||||
120 | if (!m_externalViewerProcess->waitForStarted()) { | ||||
121 | m_externalViewerProcess->deleteLater(); | ||||
122 | m_externalViewerProcess = NULL; | ||||
123 | } | ||||
124 | } | ||||
125 | return m_externalViewerProcess; | ||||
126 | } | ||||
127 | | ||||
128 | bool QtHelpProviderAbstract::externalViewerCommand(const QByteArray& command) const | ||||
129 | { | ||||
130 | if (externalViewer()) { | ||||
131 | return externalViewer()->write(command) >= 0; | ||||
132 | } else { | ||||
133 | return false; | ||||
134 | } | ||||
135 | } | ||||
136 | | ||||
137 | bool QtHelpProviderAbstract::externalViewerCommand(const char* command) const | ||||
138 | { | ||||
139 | if (externalViewer()) { | ||||
140 | return externalViewer()->write(command) >= 0; | ||||
141 | } else { | ||||
142 | return false; | ||||
143 | } | ||||
144 | } | ||||
145 | | ||||
56 | IDocumentation::Ptr QtHelpProviderAbstract::documentationForDeclaration(Declaration* dec) const | 146 | IDocumentation::Ptr QtHelpProviderAbstract::documentationForDeclaration(Declaration* dec) const | ||
57 | { | 147 | { | ||
58 | QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this); | 148 | QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this); | ||
59 | if (dec) { | 149 | if (dec) { | ||
60 | static const IndexedString qmlJs("QML/JS"); | 150 | static const IndexedString qmlJs("QML/JS"); | ||
61 | QString id; | 151 | QString id; | ||
62 | 152 | | |||
63 | { | 153 | { | ||
Show All 19 Lines | 172 | { | |||
83 | QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this); | 173 | QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this); | ||
84 | return m_engine.indexModel(); | 174 | return m_engine.indexModel(); | ||
85 | } | 175 | } | ||
86 | 176 | | |||
87 | IDocumentation::Ptr QtHelpProviderAbstract::documentationForIndex(const QModelIndex& idx) const | 177 | IDocumentation::Ptr QtHelpProviderAbstract::documentationForIndex(const QModelIndex& idx) const | ||
88 | { | 178 | { | ||
89 | QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this); | 179 | QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this); | ||
90 | QString name=idx.data(Qt::DisplayRole).toString(); | 180 | QString name=idx.data(Qt::DisplayRole).toString(); | ||
91 | return IDocumentation::Ptr(new QtHelpDocumentation(name, m_engine.indexModel()->linksForKeyword(name))); | 181 | QMap<QString, QUrl> links = m_engine.indexModel()->linksForKeyword(name); | ||
182 | // if(!links.isEmpty() && externalViewer()) { | ||||
183 | // QByteArray ba; | ||||
184 | // const auto urls = links.values(); | ||||
185 | // foreach (const auto url, urls) { | ||||
186 | // if (!url.isEmpty()) { | ||||
187 | // ba.append("setSource " + url.toString().toUtf8() + "\n"); | ||||
188 | // ba.append(QLatin1String("show contents\n")); | ||||
189 | // } | ||||
190 | // } | ||||
191 | // qCWarning(QTHELP) << Q_FUNC_INFO << "name=" << name << "->" << ba; | ||||
192 | // externalViewerCommand(ba); | ||||
193 | // externalViewerCommand("syncContents\n"); | ||||
194 | // } | ||||
195 | return IDocumentation::Ptr(new QtHelpDocumentation(name, links)); | ||||
92 | } | 196 | } | ||
93 | 197 | | |||
94 | void QtHelpProviderAbstract::jumpedTo(const QUrl& newUrl) const | 198 | void QtHelpProviderAbstract::jumpedTo(const QUrl& newUrl) const | ||
95 | { | 199 | { | ||
96 | QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this); | 200 | QtHelpDocumentation::s_provider = const_cast<QtHelpProviderAbstract*>(this); | ||
97 | QMap<QString, QUrl> info; | 201 | QMap<QString, QUrl> info; | ||
98 | info.insert(newUrl.toString(), newUrl); | 202 | info.insert(newUrl.toString(), newUrl); | ||
99 | IDocumentation::Ptr doc(new QtHelpDocumentation(newUrl.toString(), info)); | 203 | IDocumentation::Ptr doc(new QtHelpDocumentation(newUrl.toString(), info)); | ||
Show All 10 Lines | |||||
110 | { | 214 | { | ||
111 | return !m_engine.registeredDocumentations().isEmpty(); | 215 | return !m_engine.registeredDocumentations().isEmpty(); | ||
112 | } | 216 | } | ||
113 | 217 | | |||
114 | HelpNetworkAccessManager * QtHelpProviderAbstract::networkAccess() const | 218 | HelpNetworkAccessManager * QtHelpProviderAbstract::networkAccess() const | ||
115 | { | 219 | { | ||
116 | return m_nam; | 220 | return m_nam; | ||
117 | } | 221 | } | ||
222 | | ||||
223 | #include "qthelpproviderabstract.moc" |