1 | |
2 | /* |
3 | This file is part of KHelpCenter. |
4 | |
5 | Copyright (c) 2005 Cornelius Schumacher <schumacher@kde.org> |
6 | |
7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. |
11 | |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | */ |
21 | |
22 | #include "searchhandler.h" |
23 | |
24 | #include "searchengine.h" |
25 | #include "prefs.h" |
26 | #include "docentry.h" |
27 | |
28 | #include <KDesktopFile> |
29 | #include <KProcess> |
30 | #include <KDebug> |
31 | #include <KMessageBox> |
32 | #include <KLocale> |
33 | #include <KStandardDirs> |
34 | #include <KShell> |
35 | |
36 | #include <stdlib.h> |
37 | |
38 | using namespace KHC; |
39 | |
40 | SearchJob::SearchJob(DocEntry *entry) : mEntry( entry ), mProcess( 0 ), mKioJob( 0 ) |
41 | { |
42 | } |
43 | |
44 | bool SearchJob::startLocal(const QString &cmdString) |
45 | { |
46 | mProcess = new KProcess; |
47 | *mProcess << KShell::splitArgs(cmdString); |
48 | |
49 | connect( mProcess, SIGNAL( finished(int, QProcess::ExitStatus) ), |
50 | this, SLOT( searchExited(int, QProcess::ExitStatus) ) ); |
51 | |
52 | mProcess->setOutputChannelMode(KProcess::SeparateChannels); |
53 | mProcess->start(); |
54 | if (!mProcess->waitForStarted()) { |
55 | QString txt = i18n("Error executing search command '%1'." , cmdString ); |
56 | emit searchError( this, mEntry, txt ); |
57 | return false; |
58 | } |
59 | return true; |
60 | } |
61 | |
62 | bool SearchJob::startRemote(const QString &urlString) |
63 | { |
64 | KIO::TransferJob *job = KIO::get( KUrl( urlString ) ); |
65 | connect( job, SIGNAL( result( KJob * ) ), |
66 | this, SLOT( slotJobResult( KJob * ) ) ); |
67 | connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), |
68 | this, SLOT( slotJobData( KIO::Job *, const QByteArray & ) ) ); |
69 | |
70 | mKioJob = job; |
71 | return true; |
72 | } |
73 | |
74 | SearchJob::~SearchJob() |
75 | { |
76 | delete mProcess; |
77 | delete mKioJob; |
78 | } |
79 | |
80 | void SearchJob::searchExited( int exitCode, QProcess::ExitStatus exitStatus ) |
81 | { |
82 | if ( exitStatus == QProcess::NormalExit && exitCode == 0 ) { |
83 | mResult = mProcess->readAllStandardOutput(); |
84 | emit searchFinished( this, mEntry, mResult ); |
85 | } else { |
86 | mError = mProcess->readAllStandardError(); |
87 | QString error = QLatin1String("<em>" ) + mCmd + QLatin1String("</em>\n" ) + mError; |
88 | emit searchError( this, mEntry, error ); |
89 | } |
90 | } |
91 | |
92 | void SearchJob::slotJobResult( KJob *job ) |
93 | { |
94 | QString result; |
95 | //DocEntry *entry = 0; |
96 | |
97 | if ( job->error() ) { |
98 | emit searchError( this, mEntry, i18n("Error: %1" , job->errorString() ) ); |
99 | } else { |
100 | emit searchFinished( this, mEntry, mResult ); |
101 | } |
102 | } |
103 | |
104 | void SearchJob::slotJobData( KIO::Job *job, const QByteArray &data ) |
105 | { |
106 | Q_UNUSED(job); |
107 | mResult += data.data(); |
108 | } |
109 | |
110 | |
111 | SearchHandler::SearchHandler( const KConfigGroup &cg ) |
112 | { |
113 | mLang = KGlobal::locale()->language().left( 2 ); |
114 | mDocumentTypes = cg.readEntry( "DocumentTypes" , QStringList() ); |
115 | } |
116 | |
117 | SearchHandler::~SearchHandler() |
118 | { |
119 | } |
120 | |
121 | SearchHandler *SearchHandler::initFromFile( const QString &filename ) |
122 | { |
123 | KDesktopFile file( filename ); |
124 | KConfigGroup dg = file.desktopGroup(); |
125 | |
126 | SearchHandler *handler = 0; |
127 | |
128 | const QString type = dg.readEntry( "Type" ); |
129 | if ( false ) { |
130 | } else { |
131 | handler = new ExternalProcessSearchHandler( dg ); |
132 | } |
133 | |
134 | return handler; |
135 | } |
136 | |
137 | QStringList SearchHandler::documentTypes() const |
138 | { |
139 | return mDocumentTypes; |
140 | } |
141 | |
142 | |
143 | ExternalProcessSearchHandler::ExternalProcessSearchHandler( const KConfigGroup &cg ) |
144 | : SearchHandler( cg ) |
145 | { |
146 | mSearchCommand = cg.readEntry( "SearchCommand" ); |
147 | mSearchUrl = cg.readEntry( "SearchUrl" ); |
148 | mIndexCommand = cg.readEntry( "IndexCommand" ); |
149 | mTryExec = cg.readEntry( "TryExec" ); |
150 | mSearchBinary = cg.readEntry( "SearchBinary" ); |
151 | const QStringList searchBinaryPaths = cg.readEntry( "SearchBinaryPaths" , QStringList() ); |
152 | mSearchBinary = KStandardDirs::findExe(mSearchBinary, searchBinaryPaths.join(":" )); |
153 | } |
154 | |
155 | QString ExternalProcessSearchHandler::indexCommand( const QString &identifier ) |
156 | { |
157 | QString cmd = mIndexCommand; |
158 | cmd.replace( "%i" , identifier ); |
159 | cmd.replace( "%d" , Prefs::indexDirectory() ); |
160 | cmd.replace( "%l" , mLang ); |
161 | return cmd; |
162 | } |
163 | |
164 | bool ExternalProcessSearchHandler::checkPaths(QString* error) const |
165 | { |
166 | if ( !mSearchCommand.isEmpty() && !checkBinary( mSearchCommand ) ) { |
167 | *error = i18n("'%1' not found, check your installation" , mSearchCommand); |
168 | return false; |
169 | } |
170 | |
171 | if ( !mIndexCommand.isEmpty() && !checkBinary( mIndexCommand ) ) { |
172 | *error = i18n("'%1' not found, check your installation" , mIndexCommand); |
173 | return false; |
174 | } |
175 | |
176 | if ( !mTryExec.isEmpty() && !checkBinary( mTryExec ) ) { |
177 | *error = i18n("'%1' not found, install the package containing it" , mTryExec); |
178 | return false; |
179 | } |
180 | |
181 | return true; |
182 | } |
183 | |
184 | bool ExternalProcessSearchHandler::checkBinary( const QString &cmd ) const |
185 | { |
186 | QString binary; |
187 | |
188 | int pos = cmd.indexOf( ' ' ); |
189 | if ( pos < 0 ) binary = cmd; |
190 | else binary = cmd.left( pos ); |
191 | |
192 | return !KStandardDirs::findExe( binary ).isEmpty(); |
193 | } |
194 | |
195 | void ExternalProcessSearchHandler::search( DocEntry *entry, const QStringList &words, |
196 | int maxResults, |
197 | SearchEngine::Operation operation ) |
198 | { |
199 | kDebug() << entry->identifier(); |
200 | |
201 | if ( !mSearchCommand.isEmpty() ) { |
202 | QString cmdString = SearchEngine::substituteSearchQuery( mSearchCommand, |
203 | entry->identifier(), words, maxResults, operation, mLang, mSearchBinary ); |
204 | |
205 | kDebug() << "CMD:" << cmdString; |
206 | |
207 | SearchJob *searchJob = new SearchJob(entry); |
208 | connect(searchJob, SIGNAL(searchFinished( SearchJob *, DocEntry *, const QString & )), |
209 | this, SLOT(slotSearchFinished( SearchJob *, DocEntry *, const QString & ))); |
210 | connect(searchJob, SIGNAL(searchError( SearchJob *, DocEntry *, const QString & )), |
211 | this, SLOT(slotSearchError( SearchJob *, DocEntry *, const QString & ))); |
212 | searchJob->startLocal(cmdString); |
213 | |
214 | } else if ( !mSearchUrl.isEmpty() ) { |
215 | QString urlString = SearchEngine::substituteSearchQuery( mSearchUrl, |
216 | entry->identifier(), words, maxResults, operation, mLang, mSearchBinary ); |
217 | |
218 | kDebug() << "URL:" << urlString; |
219 | |
220 | SearchJob *searchJob = new SearchJob(entry); |
221 | connect(searchJob, SIGNAL(searchFinished( SearchJob *, DocEntry *, const QString & )), |
222 | this, SLOT(slotSearchFinished( SearchJob *, DocEntry *, const QString & ))); |
223 | connect(searchJob, SIGNAL(searchError( SearchJob *, DocEntry *, const QString & )), |
224 | this, SLOT(slotSearchError( SearchJob *, DocEntry *, const QString & ))); |
225 | searchJob->startRemote(urlString); |
226 | |
227 | } else { |
228 | QString txt = i18n("No search command or URL specified." ); |
229 | emit searchFinished( this, entry, txt ); |
230 | } |
231 | } |
232 | |
233 | void ExternalProcessSearchHandler::slotSearchFinished( SearchJob *job, DocEntry *entry, const QString &result ) |
234 | { |
235 | emit searchFinished( this, entry, result); |
236 | job->deleteLater(); |
237 | } |
238 | |
239 | void ExternalProcessSearchHandler::slotSearchError( SearchJob *job, DocEntry *entry, const QString &error ) |
240 | { |
241 | emit searchError(this, entry, error); |
242 | job->deleteLater(); |
243 | } |
244 | |
245 | #include "searchhandler.moc" |
246 | |